Skip to content

perf(sidebar): smooth out laggy table-list scrolling - #20

Closed
broisnees wants to merge 1 commit into
masterfrom
worktree-sidebar-scroll-perf
Closed

broisnees wants to merge 1 commit into
masterfrom
worktree-sidebar-scroll-perf

Conversation

@broisnees

Copy link
Copy Markdown
Collaborator

Problem

Scrolling the table list in the sidebar felt laggy/stuttery — content trailed the scrollbar thumb while dragging.

Root causes

  1. No GPU compositing on the scroll container. The codebase already documents (src/app.css:550) that will-change: scroll-position promotes a scroll container so WebKit runs it at the display's native rate (120Hz on ProMotion) instead of the 60Hz timer path. It's applied to the canvas table and the other virtualized lists use [will-change:transform], but the sidebar scroll container had neither — so it stuttered at 60Hz.
  2. Virtual window trailed by a frame. onSidebarScroll deferred the scrollTop read into a requestAnimationFrame, so the rendered virtual window landed one frame behind the scrollbar thumb during a drag. Reading scrollTop synchronously in the scroll handler is a cheap cached read (layout is already current), and Svelte coalesces the re-renders into one flush per frame — so the rAF only added latency.
  3. ROW_H overestimated the row stride (28px vs the real 27px: 13px text-ui-sm + py-1.5 = 25px row + 2px gap-0.5), causing minor drift between the virtual spacers and the real rows.

Changes

  • Add [will-change:scroll-position] to the sidebar scroll container.
  • Update sidebarScrollTop synchronously on scroll; drop the rAF hop and its unmount cleanup.
  • Correct ROW_H 28 → 27.

Verification

npm run build passes (only pre-existing chunk-size / dynamic-import warnings).

- Promote the sidebar scroll container to a compositing layer
  ([will-change:scroll-position]) so WebKit runs it at the display's
  native rate (120Hz on ProMotion) instead of the 60Hz timer path,
  matching the technique already used for the canvas table.
- Update the virtual-window state synchronously on scroll instead of
  deferring the scrollTop read into a rAF, which left the rendered
  window one frame behind the scrollbar thumb during a drag.
- Correct ROW_H (28 -> 27) to match the real row stride (25px row +
  2px gap) so virtual spacers don't drift.
@changeset-bot

changeset-bot Bot commented Jul 5, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 7fba212

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@broisnees

Copy link
Copy Markdown
Collaborator Author

Superseded by combined minor-release PR #36 (same changes, rolled up). Closing to keep a single merge.

@broisnees broisnees closed this Jul 5, 2026
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 5, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant