fix(next): sidebar toggle content follows its frame, no landing snap (carry #28894)
Carry of #28894 (its lane's host could not be reached and the branch had no commit since 2026-10-31 04:17Z). The original commits are kept unchanged, with feat-cmux-next merged in (clean merge, no conflict).
Leo (2026-10-31): "also the toggle of opening and closing the left sidebar it's just too wonky it snaps and jitters after it overshoots and needs to correct itself"
Cause
The sidebar's width itself animates on a monotonic ease-out curve (no spring, so no overshoot of the sidebar edge). The overshoot-then-correct comes from the content beside it: with sidebar.slideHoldsContent on (the default since the 2026-10-21 GPU audit), the panes keep the wider of their start and end widths through the whole slide and only resize once the slide lands. On a show, the content sits wider than its final width for the whole slide and then snaps narrower at landing (terminals reflow, pages relayout): the "overshoots and needs to correct itself" frame. The completion also published "motion ended" before the final constraint layout was flushed, so content could hear settlement at a stale width and correct a frame later.
Change
sidebar.slideHoldsContentdefaults to off: the content follows the card's edge every frame, so there is no second resize at landing. The hold stays in Debug Settings as an opt-in comparison.SidebarContainerView: both the animated completion andsnap()flushsuperview.layoutSubtreeIfNeeded()at the target width before clearingisWidthAnimating, so content and terminal geometry are final when they hear the motion ended.- Tests:
SidebarToggleSettlementTestssamples every display frame of show, hide and a mid-flight reversal and fails on any width outside its endpoints, any frame moving away from the target, content not matching the card, or any geometry change after settlement (GUI-gated,CMUX_TEST_REQUIRE_GUI=1).SidebarSlideHoldsContentTestsnow pins the hold on explicitly and checks the new default. scripts/cmux-next/media/states/sidebar-toggle-motion.json: a capture state for recording the toggle.
Risk
The content now lays out at a new width on each frame of the ~0.25 s slide, the cost the 2026-10-21 GPU audit measured as offender #1 (6.7 to 7.4 ms of main thread per frame with many panes). That trade is what removes the landing snap; the hold remains available under Debug Settings for comparison. No other component, default or Chief path is touched.
Agent session: agent session
š¤ Generated with Claude Code
![View with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png)
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Carries #28894 (its lane's host was unreachable, with no commits since 2026-10-31) with feat-cmux-next merged in cleanly. Fixes the left sidebar toggle that "snaps and jitters" after it settles.
The snap came from sidebar.slideHoldsContent keeping content wider than its final width for the entire slide and resizing once at landing, while the "motion ended" signal could fire before the final layout was flushed.
- Content now follows the card's edge on every frame;
slideHoldsContentdefaults to off and remains in Debug Settings as an opt-in comparison. SidebarContainerViewflusheslayoutSubtreeIfNeeded()at the target width before publishing the motion ended; a flush that retargets the sidebar starts a newer leg and leaves its motion flag set.- Adds
SidebarToggleSettlementTestssampling every display frame of show, hide, and mid-flight reversal, plus a capture state for recording the toggle. - Trade-off: panes relayout at a new width each frame of the ~0.25 s slide (the 2026-10-21 GPU audit's offender #1); the hold stays available under Debug Settings.