Skip to content

feat(app): open sidebars with a short fade, close them instantly - #57880

Closed
jlongster wants to merge 3 commits into
betafrom
sidebar-fade
Closed

jlongster wants to merge 3 commits into
betafrom
sidebar-fade

Conversation

@jlongster

@jlongster jlongster commented Oct 21, 2026 •

Copy link
Copy Markdown
Collaborator

Issue for this PR

Closes #

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

Changes how the left sidebar and the side panel open and close. #56996 made them instant. #57692 (merged today) brought motion back by springing their real layout width every frame, tunable from the Motion workspace's Knobs "Sidebars" section. This PR replaces that width spring, and the "Sidebars" Knobs section with it, with the values James picked in the real app, hardcoded:

  • Open:
    • Layout changes in one frame.
    • The panel shifts in from its edge: side panel 12px, left sidebar 10px, mirrored in RTL.
    • Shift easing: spring of 240ms, bounce 0 (k 685, c 52.4, ζ 1), no delay.
    • At the same time it fades from opacity 0.15 to 1 on cubic-bezier(0.44, 0.75, 0.63, 1.03) over 180ms, no delay.
  • Close: instant, with no shift and no fade. Closing during an opening cancels it and hides the panel at once.
  • Always instant: keyboard toggles (⌘⇧B, ⌘⇧R, palette Enter), reduced motion (the app setting or the OS), and switching to a session whose side panel is in the other state.

Why it's cheap:

  • Both opening animations are Web Animations on transform and opacity. The spring is sampled once into a CSS linear() easing; a unit test checks it point by point against x(t) = 1 − (1 + ωt)e^(−ωt) with ω = 2π/0.24.
  • The compositor plays them: no per-frame JS, layout or style work.
  • They keep playing through main-thread stalls, such as the side panel's first open mounting its region.
  • In the real app (40-turn session, dev build, 4× CPU throttle), opening by click cost about the same layout and style time as an instant keyboard toggle. Side panel: about 12 layouts either way. feat(app): bring back tunable sidebar motion #57692's own table shows 17–40 layouts per toggle for the width spring.

Code:

  • shell/panel-motion.ts: createPanelMotion({ open, element, offset, identity }) plays the opening and exposes whenSettled (focus moves into the panel after it lands). panelsMoving still hides native views during an opening.
  • releaseClosedFocus replaces guardClosingFocus: with no closing flight, it only moves focus out at the moment of close.
  • The Knobs spring, the Spring/Instant choice, the replay buttons, sync, and the closing-pointer blockers are removed.
  • Chat and sidebar widths are declarative again.
  • sidebar-toggle.tsx and the titlebar's handoff go back to their pre-feat(app): bring back tunable sidebar motion #57692 versions.
  • SideRegion loses its present prop.
  • Kept from feat(app): bring back tunable sidebar motion #57692: the side region stays mounted after its first open and is skipped with content-visibility: hidden when closed, so reopens don't remount.

Known: the side region still mounts on its first open, as before; the fade plays through that stall on the compositor.

How did you verify your code works?

  • bun typecheck in packages/app.
  • bun test --conditions=browser --isolate --preload ./happydom.ts ./test-browser/panel-motion.test.ts: 7 pass. Covers the exact keyframes, easings, durations and spring samples; instant close cancelling an opening and dropping its queued work; keyboard; reduced motion; layout switch; and focus release on close.
  • e2e/regression/panel-edges.spec.ts is updated for the instant close: the layout moves in one frame, an open fades over several frames from 0.15, a close doesn't animate, and keyboard toggles don't animate, in LTR and RTL.
  • An earlier revision (fade on close as well) was exercised in the real beta web app against an isolated OpenCode Drive server, and its e2e failures matched beta's. James will check the instant close himself; I didn't re-run e2e or Desktop on this revision.

Screenshots / recordings

Recordings of an earlier revision are on the team canvas, group "Sidebar motion": https://jamesbox.exe.xyz/canvas/c/mSxZCqwqak. James is checking this revision directly.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

@jlongster jlongster changed the title feat(app): fade sidebars in place instead of springing their width feat(app): open sidebars with a short fade, close them instantly Oct 21, 2026
@jlongster

Copy link
Copy Markdown
Collaborator Author

Replaced by #57901, which adds this as a "Low movement" option alongside Kit's sidebar motion (#57692) instead of replacing it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant