Repository navigation
Conversation
…he slide the title row rode the content root's slide with the hidden layout's padding, so a show carried it a sidebar width right and snapped it back at the landing, and a hide threw it right at the keypress. it now sits in its own layer and glides from its hidden rest to its docked rest on the same spring, render server only. its padding and the titlebar border follow the docked layout flag, so they change in the same commit as the layout. minimal mode's tab bar inset now changes inside the atomic layout commits, and the first pane's tabs ride the slide as a picture that glides by the inset over plain tab bar. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
the slide carries the full-width layout past the content's trailing edge, so the action buttons of panes on that edge slid out under the right sidebar and popped back at a show's landing, and vanished at a hide's press. they rest at the same x in both layouts, so the slide now shows a still picture of them in place, taken at the press, and drops it in the landing commit. also fixes the pane lookup the minimal tab row picture relies on (split leaves are plain hosting views in a split slot, and the tab bar background shares the tab hit region protocol), keeps pictures through display passes, and moves the slide session into its own file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
bonsplit keeps split ratios, so the hidden layout's panes are wider in proportion and one rigid slide carried every edge past the leading one too far: a show threw an inner divider, the pane right of it and the left pane's buttons about 120 pt past their place for a 50/50 split and snapped them back at the landing, a hide the mirror. now each split slot (and a lone pane) moves by its own leading edge relative to the slot around it and clips at its own trailing edge, the portal's terminal and browser views follow their pane, divider strips in each split's colour ride the gaps (the portal's divider overlay is faded out meanwhile), and each pane's action buttons ride its trailing edge as a picture. all of it is spring animations in the same transaction, render server only. the docked rects come from the hide's press, from the last hide over the same hidden layout, or failing both from bonsplit's rule. adds a DEBUG per-frame edge log (CMUX_SIDEBAR_SLIDE_EDGES) for checking the motion without screenshots. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ays flush with its pane per-pane motion now covers everything drawn for a pane, by construction: - the portals' views (terminals, browser pages, in or out of window glass) come from the portals' own entries and follow the pane their anchor sits in, glided and clipped - each pane's trailing chrome is pictured from the layout that is live for the slide (a hide's right after its commit) and rides the pane's trailing edge as a sublayer of the pane's own clip, so it always sits flush and whole inside the pane and can never leave it. the tab bar's part is bonsplit's action lane by its fixed width; other bars (browser toolbar, path bar, composer) are cut at a seam between rows alike all the way across, only the bar at the strip's edge, never more than half the pane, never in a web view - overlays inside a portal view keep their anchoring by geometry (scroller, badges trailing, cards centred), drawn ones (find bars, rings, borders) are pictured and cut the same way inside the view's clip - bonsplit's own divider drawing is blanked for the slide (the strips stand in), and overlays painting at every pane's rect at once (portal divider, pane swap, drop zones, tmux rings, cloud failure card) are hidden with an empty mask, which survives the portal re-adding them - minimal mode's leading tabs ride inside the leading pane's clip - a bonsplit split resize mid-slide (a split, a close) lands the slide at once on the new layout the debug edge log now includes browser pages and the trailing pictures, and a layer dump (CMUX_SIDEBAR_SLIDE_LAYER_DUMP) for finding strays. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
tab chips cut by the action lane picture read as broken. the tab bars now lay themselves out at the pane's visible width every frame (bonsplit's new tab bar width hook, driven by a display link on the slide's own clock), so tabs truncate for real with their ellipsis and close button and the action lane is live, whole and flush with the pane's moving trailing edge. no tab row pictures remain. the slide's clock now starts at core animation's actual begin time, so the per-frame width follows the spring frame for frame. a split or close mid-slide now rebuilds the slide for the new layout and goes on from where it is with its speed, instead of landing at once. points vendor/bonsplit at a local commit (needs its own bonsplit pr). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
on a hide the panes' action buttons bounced: the tab bars were laid out on the main thread a frame or more behind the pane edges core animation moves (about 25 ms a frame in debug, and the first frame of a hide showed the full hidden width before any slide width applied). the lane is now a picture of bonsplit's own lane, at the width bonsplit reports, riding the pane's trailing edge on the same spring as the edge, with bonsplit's real lane hidden for the slide. the tabs still lay out live, but at the narrower of this frame's width and the width 34 ms on, so a missed frame only shows a little bar surface before the lane, never tabs under it. the first frame lays out at the slide's start pose, and every width applies in the same transaction (needsLayout before layoutSubtreeIfNeeded). points vendor/bonsplit at local 5b3623d. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
lucas saw a black gap and a stale title fragment in a tab bar mid-slide. the tabs were laid out on the main thread every frame, a frame or more behind the pane edges core animation moves, so they jumped and left bare bar before the lane. the lane picture was also cut from the whole bar: the ground behind it (the black) and the fading end of a long title under the lane (the fragment). now each tab bar is laid out once at its pane's own width for the whole slide, so the tabs and their scroll offset never move, and masks riding each pane's trailing edge on the slide's spring fade the tabs and the selected tab's indicator exactly where bonsplit fades them at rest. the lane picture is the lane alone, on clear: its buttons and the bottom line under it. no per-frame tab layout or display link is left. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configuration
You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Unclear: CI failed on
Not re-run automatically: Written by |
Dogfood tours of
|
the layout observer was only removed on teardown, so a window closed mid-slide left it registered for the life of the app.
…ot, so files don't flicker brighter mid-slide
|
Agents: |
…class name checks each press pictured every tab bar strip with cacheDisplay and then threw it away, since tab bars only use the lane picture. skipping it about halves the press-time capture with 6 panes (45-65 ms down to 15-33 ms in debug). class name checks run on every view in the window at the press, so their answers are kept per class. debug-only timing laps for the press too.
a browser pane crosses the toolbar's 420 pt compact width when the sidebar toggles, so the pen and dev tools buttons popped in or out mid-slide. the toolbar now holds its compact state while a slide runs and fades the change in once it lands.
a horizontal divider's stand-in strip both moves and widens, but every glide was added under the same key, so the width animation replaced the move. the strip's left end started about 120 pt right of the pane edge and only caught up at the landing, leaving the border above a lower pane cut short mid-slide. debug-only CMUX_SIDEBAR_SLIDE_STRIP_DEBUG draws the strips red to check them.
appkit draws a split view's divider into its own content sublayer and redraws it during a show, which put back the contents the slide had blanked. the real divider then rode with the content root next to its stand-in strip, a second vertical line ending about 120 pt off. an empty mask, which appkit leaves alone, keeps it hidden for the whole slide.
…r text hold still through the slide - the workspace card's 8pt bottom inset showed as a dead strip under a browser page - compact toolbars show the import chip as a square icon, so it never truncates to "I..." - the omnibar clips its text and placeholder instead of ellipsizing or wrapping, so a slide's landing doesn't snap "Search or enter URL", focused or not
with the right sidebar closed the 8pt trailing inset showed as a strip beside a browser page
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 4 potential issues.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit c51366e. Configure here.
| self.isPeekPresenting = isPeekPresenting | ||
| self.dockedLayoutWillCommit = dockedLayoutWillCommit | ||
| self.tabBarInsetDelta = tabBarInsetDelta | ||
| self.splitButtonCount = splitButtonCount |
There was a problem hiding this comment.
Reinstall leaves slide flag stuck
Medium Severity
A re-install drops the running session and resets the machine, but never calls markSliding(false). isSliding can stay true and slideDidLand never posts, so browser chrome that captured heldChromeCompact stays frozen after the view reappears mid-toggle.
Reviewed by Cursor Bugbot for commit c51366e. Configure here.
| guard sliding != Self.slidingAnimators.contains(id) else { return } | ||
| if sliding { Self.slidingAnimators.insert(id) } else { Self.slidingAnimators.remove(id) } | ||
| Self.isSliding = !Self.slidingAnimators.isEmpty | ||
| if !sliding { NotificationCenter.default.post(name: Self.slideDidLand, object: nil) } |
There was a problem hiding this comment.
Land notification is process-global
Medium Severity
markSliding(false) always posts slideDidLand with no window, even when other animators are still in slidingAnimators. Every BrowserPanelView then clears heldChromeCompact, so a second window's landing can pop the first window's toolbar mid-glide.
Additional Locations (1)
Reviewed by Cursor Bugbot for commit c51366e. Configure here.
| // observer goes with it. | ||
| removeSlideAnimations() | ||
| markSliding(false) | ||
| return |
There was a problem hiding this comment.
Closed window leaves machine sliding
Medium Severity
When window() is nil mid-slide, teardown clears the session and isSliding but never lands or resets the machine. machine.slide stays set, so a later press on the same animator retargets a ghost slide instead of starting cleanly.
Reviewed by Cursor Bugbot for commit c51366e. Configure here.
| backgroundColor: appearance.resolvedChromeBackgroundColor | ||
| ) | ||
| .padding(.leading, sidebarState.isVisible ? width : 0) | ||
| .padding(.leading, sidebarState.isVisible && sidebarLayout.docksSidebar ? width : 0) |
There was a problem hiding this comment.
Titlebar hairline snaps on hide
Medium Severity
The titlebar hairline inset now follows docksSidebar, which flips at hide start, but this border lives in the window overlay and has no glide. The line jumps to the window's leading edge while the sidebar is still on screen.
Reviewed by Cursor Bugbot for commit c51366e. Configure here.


summary
stacked on #18334 (organize/drag). this is the cmd b sidebar toggle glide, split out as lawrence suggested.
when the sidebar hides or shows, every pane now glides to its own docked edges on the same spring as the sidebar, instead of the old rigid slide:
needs the bonsplit change in manaflow-ai/bonsplit280 (
vendor/bonsplitpoints at it).testing
known leftovers
Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.Summary by cubic
Reworks the cmd+B sidebar toggle so each pane glides to its own docked edges on the same spring as the sidebar, replacing the previous rigid slide of the whole content root. The titlebar title, minimal-mode tab bar inset, and each pane's trailing action lane glide in step, content is clipped to each pane's rect so nothing leaks into neighbors, and tab bars are laid out once at the pane's width so tabs and their scroll offset hold still and fade at the moving edge. The live right sidebar is held still against the moving root instead of snapshotted, so file views don't flicker brighter mid-slide. The browser toolbar holds its compact state through a slide and fades the change on landing, so its tools don't pop in or out mid-motion. One layout commit and one terminal resize occur per toggle, and closing the window mid-slide drops the slide cleanly instead of leaving a stale layout observer for the app's lifetime. The workspace card now runs flush to the window's bottom and trailing edges, so no dead strip appears under a browser page; the compact toolbar's import chip shows as a square icon, and the omnibar clips its text rather than ellipsizing, so neither shifts at the slide's landing.
Fixes
manaflow-ai/bonsplit280(vendor/bonsplitpoints to it).Known leftovers
Tested by hand on a dev build and with GlideLab pixel checks across multiple layouts, speeds, and light mode.
Written for commit c51366e. Summary will update on new commits.
Note
Medium Risk
Large Core Animation and layout-timing changes across window chrome, Bonsplit panes, and portal geometry; depends on vendor Bonsplit slide-width APIs and has known edge cases (mid-split toggle, fullscreen/peek not fully verified).
Overview
Replaces the cmd+B sidebar toggle rigid content-root slide with per-pane motion on the same spring: panes, portal-hosted terminals/browsers, split dividers, tab action lanes, and titlebar title (via
SidebarSlideGlideHost) each glide/clip between hidden and docked layouts using new capture/layout/glide machinery (SidebarSlidePaneLayout,SidebarSlidePaneChrome,SidebarSlidePaneGlide,SidebarToggleSlideSession).SidebarToggleAnimatornow captures docked geometry at hide press, rebuilds mid-slide on split resize (restart), syncs minimal-mode tab bar inset on dock commits, exposesisSliding/slideDidLandso UI (e.g. browser toolbar compact state, omnibar clipping) holds steady until the slide lands. Right sidebar column stays live (inverse spring + masks) instead of a snapshot overlay.Chrome polish: workspace card drops bottom/trailing pane insets and bottom-leading rounding; traffic-light tab inset respects docked vs hidden; browser import chip goes icon-only in compact mode; portal registry types loosened for slide introspection (
entriesByWebViewId,Entry). DEBUG probes/timings extended; unit tests cover glide math, action-lane width, and slide restart.Reviewed by Cursor Bugbot for commit c51366e. Bugbot is set up for automated code reviews on this repo. Configure here.