Skip to content

perf(app): skip layout and paint of rows out of sight - #83

Merged
httpsphl merged 1 commit into
mainfrom
perf/offscreen-rows
Oct 1, 2026
Merged

httpsphl merged 1 commit into
mainfrom
perf/offscreen-rows

Conversation

@httpsphl

@httpsphl httpsphl commented Oct 1, 2026

Copy link
Copy Markdown
Owner

Second performance round, slice 4.

What

The chat (ChatView) and a crew's message timeline (Timeline) keep every page loaded so far ("Load earlier" never trims), with no virtualization. Each new row, and each streamed draft update, re-ran layout over all of them.

New app/src/offscreen.css gives content-visibility: auto to the rows of any list marked offscreen-rows. contain-intrinsic-size: auto 120px means a row that was rendered once keeps its real height, so the scrollbar does not jump. Chromium (WebView2) then skips layout and paint for rows out of sight until they scroll near.

The 8 newest rows are left out on purpose:

  • That is where approval, plan and suggestion cards arrive with the attention glow, a 14 px box-shadow. The paint containment that comes with content-visibility would clip it.
  • It is also the part of the list the owner looks at.

This is pure CSS: no list component changed besides a class name. The spec (section 15, after the polls note) describes it.

Checks

  • pnpm check: 44 files, 258 tests pass.
  • In the pnpm dev preview with FakeBotloft, I sent 14 multi-line messages to Scout (18 rows):
    • 10 rows got content-visibility: auto and the last 8 kept visible;
    • the chat stayed pinned to the bottom (1 px from the end);
    • scrolling to the top rendered the earliest rows (day divider, image, tool line) normally.

Manual check (real Claude)

In a long real chat (several "Load earlier" pages), scroll up and down quickly. Rows appear without blank flashes, the view does not jump, and "Load earlier" keeps the reading position.

The chat and a crew's messages keep every loaded page in the DOM, and
each new row or streamed draft re-laid them all out. Rows out of sight
now use content-visibility: auto, with the size they last had, so the
browser skips them until they scroll near. The 8 newest rows are left
out, since cards arrive there with a glow that paint containment clips.
@httpsphl
httpsphl merged commit 550e4c3 into main Oct 1, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant