perf(app): keep hidden sidebar rows windowed on resize - #2000
Closed
ymichael wants to merge 1 commit into
Closed
Conversation
ymichael
force-pushed
the
bb/pr-2-responsive-sidebar-windowing-thr_85dv9qb78t
branch
2 times, most recently
from
August 20, 2026 18:08
941bb51 to
7f4678a
Compare
ymichael
force-pushed
the
bb/pr-2-responsive-sidebar-windowing-thr_85dv9qb78t
branch
from
August 20, 2026 18:10
7f4678a to
0f20a6e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What was wrong
During compact drawer breakpoint/orientation transitions,
SidebarWindowedItemstreated a not-yet-attached ref or a connected scrollport reporting transient zero-height geometry as an unusable viewport and synchronously promoted every placeholder. The pre-paint geometry pass also considered only vertical overlap, so a closed compact drawer translated offscreen could promote all of its rows. IntersectionObserver pruned them again after layout, but WebKit had already rendered and laid out the hidden thread tree. This is a follow-up to #1261.What changed
alwaysMountedKeysrows while preventing newly overlapping hidden rows from being promoted.There are no wire, host-daemon protocol, CLI, SDK, or configuration changes;
HOST_DAEMON_PROTOCOL_VERSIONis unchanged.How you verified
The new null-ref, connected-zero-height, and closed-drawer tests fail against the baseline implementation and pass with this change.
pnpm exec turbo run test --filter=@bb/app -- --run src/components/sidebar/SidebarWindowedItems.test.tsx— 7/7 passed.pnpm exec turbo run test --filter=@bb/app --force— 398 files passed; 3,046 tests passed and 3 skipped.pnpm exec turbo run typecheck --filter=@bb/app— passed.iOS Simulator Safari profile
I profiled both variants from the same fetched
origin/mainbaseline (2cf68c69b, the tip when capture began), using the same seeded database and scenario. The branch was subsequently rebased through currentorigin/main(4bf34b590); those later upstream commits do not touch either sidebar-windowing file. The focused tests and app typecheck passed on the same patch after the preceding rebase, and the final rebase was conflict-free; the full app suite and wide-sidebar smoke check had already passed before these upstream-only rebases.Configuration: iPhone 16 Pro Simulator, iOS 18.4 Safari, Xcode 26.6 on macOS 26.5.1, Vite development build. Fixture:
pnpm seed:perf -- --reset --projects 12 --threads 1200 --events 400000 --seed 4242, producing 12 projects, 1,200 threads, 402,148 events, and 145 windowed sidebar groups. Each variant ran 7 identical landscape cycles: compact closed -> open -> close -> 900px wide breakpoint -> 393px compact breakpoint -> reopen -> close, with two animation frames plus 280 ms settling after each action.Peak realized rows were sampled with a subtree MutationObserver. Main-thread stalls were sampled as requestAnimationFrame gaps over 50 ms, and “blocking” is the accumulated time beyond 50 ms. Style/layout timing is the sum of six forced
getComputedStyle/getBoundingClientRect/scrollHeightcheckpoints per cycle. Values are median (range), in milliseconds except row counts.The row peak dropped 98.6%, the median worst frame gap dropped 52.3%, and median excess frame-blocking time dropped 59.0%. The small forced style/layout sample was noisy and did not improve; the material gain came from avoiding the transient React realization and its associated long main-thread stall. The remaining profiling caveats are development-build overhead and Simulator rather than physical-device hardware.
Fixes #1261