fix(sidebar): paint channel rows with the scroller contents - #428
Conversation
The channel list scroller was not a stacking context, so WebKit promoted each row's positioned layers (~132) into proxy layers that lag fast scrolls. Isolating the scroller keeps them in its scrolled contents. Signed-off-by: Pinky <5f5ab050ec58ae208332edd544ebf705221e24c1b86d82a6ca07038a7a8f6ac9@buzz.block.builderlab.xyz>
wesbillman
left a comment
There was a problem hiding this comment.
Star Lord automated source review
Posted via Wes’s GitHub account; this is a non-blocking COMMENT, not approval.
No actionable defects identified in this diff. Reviewed head 9e2a02975ba163ca03e06fb514ae00de7e02f5d4 against base 4d1c5da9c8bc4ea9d968990ee9c509b05c85776f using hash-verified source blobs (no working-tree inputs).
The change is limited to isolation: isolate on the sidebar nav. I traced row/section stacking, the sibling unread controls and resize handle, portaled menus/popovers/tooltips, and success/cancel/error/retry focus paths. I found no source-demonstrated regression from the new stacking context. The public description and changed file were also inspected; the description contains no attached images. No actionable public-material privacy finding identified.
Validation limits: source-only; I did not execute PR code, launch the app, or reproduce native scrolling. The description’s native/116-test evidence predates the rebase, and human acceptance remains deferred. A read-only snapshot of checks attached to this head shows CI required failing: WebKit shard 2/6 reports 63 passed / 1 failed. agent-control.spec.mjs:402 expected “Could not confirm” but received “Could not refresh local agents. Current host status is unconfirmed.” I have not established that failure’s cause or a connection to this CSS change; CI remains unresolved. This review does not establish native compositor performance, fix the separately documented timeline flicker, or attest merge readiness.
wpfleger96
left a comment
There was a problem hiding this comment.
🤖 I don't see any blockers at 9e2a0297. Thanks for the rejected-.feed section. It saved me from asking why the timeline wasn't isolated too.
The <nav> doesn't set position, so isolation: isolate only collapses its contents into one layer at the frame's z-auto level. Everything that has to stay on top sits outside the nav and already outranks it: the frame's scrollbar covers (::before z 3, ::after z 2 and later in tree order), the Unread pills (z 3, siblings of the nav in SidebarUnread.tsx), and the resize handle (z 4, outside the sidebar wrapper). Inside the nav the highest z-index is the row .disclosure at 2, and row ::before/children and .sectionActions keep their order relative to each other. The row, section, and status menus/popovers/tooltips all go through Base UI portals, so none of them get trapped. I couldn't find any sticky, blend-mode, or negative z-index dependency in the sidebar tree.
I also ran a headless WebKit comparison of head vs base (production build, 130 rows, light and dark). All 42 overlay observations matched. The pills own their hit points and reveal/focus without changing the selection. Section hover actions, the more-actions menu, collapse, and Create channel work at 220/260/520px widths. Row menu Mute/Unmute works. Resize drag and double-click reset work. The scrollbar covers keep the same computed z-index and pointer-events: none. None of this covers the native compositor improvement, so the fast-flick check in your human test is still the real acceptance gate.
The red CI required comes from agent-control.spec.mjs:322 on webkit 2/6. The same test fails on recent main runs (d28b0d39, d7414652). Both of its cases passed 3/3 locally at head and at base, so I don't think it's from this diff.
* origin/main: Polish top bar and animate contextual sidebar toggle (#360) fix(profiles): preserve nonlocal agent identity in profile fallback (#327) test(agents): pause the status poll around the failed-Stop checks (#431) fix(sidebar): paint channel rows with the scroller contents (#428) Signed-off-by: Sol <49aa1f65411fd096d2e2ec144f1e7aa36fdc76d1b907cfdf7be000c66f9d3b8e@buzz.block.builderlab.xyz>
* origin/main: (58 commits) flake fix: keep restored reading anchor out of bottom follow (WebKit scroll measurement) (#407) Replace fixed browser-test waits with conditions, gates and the clock (#373) feat(updates): show installed version in Software Updates settings (#430) fix(desktop): allow deep-link delivery to the main webview (#432) feat(shell): open your profile from the account menu avatar (#390) Polish top bar and animate contextual sidebar toggle (#360) fix(profiles): preserve nonlocal agent identity in profile fallback (#327) test(agents): pause the status poll around the failed-Stop checks (#431) fix(sidebar): paint channel rows with the scroller contents (#428) feat(channels): archive and delete channels from settings (#385) feat(updates): add in-app auto-updates with restart toast (#312) fix(ui): keep background loading from shifting populated views (#418) Improve member and agent identity previews (#412) Fix initial emoji autocomplete selection (#419) Add community membership settings (#348) Keep nested replies compact and place actions above message text (#367) Import an exact inventory identity from its selected source with retry (#288) ci: add gated macOS preview updater feed promotion (#414) Set up incomplete inventory identities through a working Use here dialog (#287) Show saved local and relay inventory while retaining existing import controls (#286) ...
* origin/main: (58 commits) flake fix: keep restored reading anchor out of bottom follow (WebKit scroll measurement) (#407) Replace fixed browser-test waits with conditions, gates and the clock (#373) feat(updates): show installed version in Software Updates settings (#430) fix(desktop): allow deep-link delivery to the main webview (#432) feat(shell): open your profile from the account menu avatar (#390) Polish top bar and animate contextual sidebar toggle (#360) fix(profiles): preserve nonlocal agent identity in profile fallback (#327) test(agents): pause the status poll around the failed-Stop checks (#431) fix(sidebar): paint channel rows with the scroller contents (#428) feat(channels): archive and delete channels from settings (#385) feat(updates): add in-app auto-updates with restart toast (#312) fix(ui): keep background loading from shifting populated views (#418) Improve member and agent identity previews (#412) Fix initial emoji autocomplete selection (#419) Add community membership settings (#348) Keep nested replies compact and place actions above message text (#367) Import an exact inventory identity from its selected source with retry (#288) ci: add gated macOS preview updater feed promotion (#414) Set up incomplete inventory identities through a working Use here dialog (#287) Show saved local and relay inventory while retaining existing import controls (#286) ... Signed-off-by: Elrond <28d6302a099e5225b02c4155ac4236e4912603df2ab08dbfc2f4fef08ce598c8@buzz.block.builderlab.xyz>
Summary
This makes the sidebar channel list (
.channelList) a stacking context withisolation: isolate.Without it, WebKit gives each row's positioned layers (
::beforeat z-index 0, children at z-index 1) their own scrolling-proxy layer. That's about 132 layers, and their tiles fall behind during fast flicks. With the change, rows paint in the scroller's own scrolled contents.This improves the sidebar only. It does not fix the timeline flashing.
Native evidence
0a498279plus this diff. The baseline is the same build withisolation: auto !importantinjected on the nav.Rejected: isolating the timeline scroller (false win)
Adding the same property to
.feedat first showed timeline dips dropping to 0. The drop happened because the timeline was barely scrolling. All rows below use the same native input:.feed+.channelListisolated (×7 runs).feedisolated, Virtua Mac momentum interrupt disabled.feedwithwill-change: transform(0 proxies, scrolling intact).feedisolated, many flicks were dropped outright or lost their momentum.overflow-ytoggle inpatches/virtua@0.51.0.patch.Still unproven
f0c6ac89) shows them too in this harness, so no regressing commit has been identified.Overlay check
::beforez-index 3,::afterz-index 2), the Unread edge pills (z-index 3) and the resize handle (z-index 4).Validation
biome checkpasses on the changed file.sidebar-unread,navigation-sidebar,navigation-scroll-intent,layout,menu-dismiss,navigation-groups,navigation-session-menu.0a498279plus this diff. The branch was then rebased onto4d1c5da9, and none of those checks were rerun on the rebased head.Channels.module.cssis unchanged by the 9 new base commits, but they do change nearby sidebar code and shared inputs:src/features/channel-navigation/ChannelSidebar.tsxandtests/browser/sidebar-unread.spec.mjs(fix(ui): keep background loading from shifting populated views #418: sidebararia-busy, startup notices removed)src/shared/design-system/styles/components.css(Improve member and agent identity previews #412: preview-card positioner stacking)tests/browser/fixture.mjs(Add community membership settings #348) andtests/fixtures/{messages,emoji}.tsx9e2a0297is the check for the rebased head.9e2a0297and found no blocking issues. He also verified the corrected evidence above.9e2a0297Human test (native app)