feat(desktop): the side panel drags until the document's floor, and full screen asks a longer pull
Dean asked to tune drag-to-expand on the right panel: let the main column get skinnier, make full screen need a longer pull, and find out whether expand used the same mechanics and values as collapse.
Did expand and collapse share mechanics and values? Yes, both.
On main, use-resizable-edge.ts used one SNAP_OVERSHOOT = 80 and one SNAP_HYSTERESIS = 24 for both directions:
- Collapse: the panel shut once the drag asked for less than
MIN − 80= 280 − 80 = 200px. It let go again above 224. - Expand: the panel went full screen once the drag asked for more than
max + 80.maxwasmin(720, plan area − 360), so on a typical window the panel stopped at a fixed 720px with the document still wide, and 80px of extra pull filled the window. It let go again belowmax + 56.
The pointer distance was the same both ways. Expand felt early for two reasons: it stopped at an arbitrary 720 rather than at a limit you can see, and the same 80px then covered the whole document instead of shutting one pane.
What changes
- The panel has no fixed greatest width. It drags until the document reaches its floor, as an editor's secondary side bar does.
SIDE_PANEL_WIDTHkeepsMIN280 andDEFAULT400;MAX720 is gone. - The document's floor is lower, and it follows the sidebar. It is declared once in CSS as a registered
@property --document-reservelength. The panel'smax-widthuses it, and the drag reads it when a drag or key press starts. There is no number duplicated in TypeScript.- Sidebar open: the floor is 280px, down from 360 and equal to the panel's least width, so the two panes have the same floor.
- Sidebar folded: the floor is 280px plus the clearance the toolbar spends getting past the traffic lights and title-bar buttons (
--sidebar-toggle-clearance − --column-inset), which is 423px today. A change to that clearance moves this floor with it.
- Collapse is unchanged: it still snaps 80px past the least width (
COLLAPSE_OVERSHOOT). - Full screen needs twice the pull: 160px past the greatest width (
EXPAND_OVERSHOOT). - Hysteresis is still 24px in both directions.
- Same live snap as #1850: it snaps mid-drag, a drag back undoes it, there is no preview, and a snap keeps the width you had.
- The edge's announced range follows the room. With no fixed maximum, the separator measures the room its container allows whenever the container resizes, and announces it as
aria-valuemax.aria-valuenowis the width actually drawn, so the value always falls inside the range (Devin flagged the missing maximum). - The sidebar's edge is unchanged:
MAX400, a 360px reserve, the same 80px collapse, and no expand action. The hook'sreserveoption became a function, so the sidebar passes() => WORK_RESERVE.
Why the folded floor is larger
I measured the plan toolbar in headless Chrome.
| Floor | Plan tab | Copy plan | ⋯ |
|---|---|---|---|
| 280px, sidebar open | 103px | fits | fits |
| 280px, sidebar folded | 0px | fits | pushed past the edge, under the panel, so it can't be clicked |
360px (main), sidebar folded | 40px, shows only "T" | fits | fits |
| 423px, sidebar folded | 103px | fits | fits |
The folded toolbar starts 155px in to clear the title-bar buttons, which is why it needs the extra room. The orchestrator approved this split.
Evidence
CI could not verify the Mac UI, and ./scripts/verify.sh was not run. This was built on a Linux cloud VM; LUKE-159 is the manual Mac pass.
I checked the real renderer components and the built styles.css in headless Chrome 154, driving the edge with CDP mouse drags in 4px steps. The window was 1200px wide with the sidebar folded:
| Pointer | Panel |
|---|---|
| at the floor | 777px wide, document 423px |
| 93px past the floor | still 777px |
| 153px past the floor | still 777px |
| 168px past the floor | full screen |
| back 15px | still full screen |
| back 35px | 777px again |
With the sidebar open, the document stops at 280px. With the panel at its widest, the document still shows its plan tab ("Teamm…"), Copy plan and ⋯, and the call bar reads in full. I couldn't attach the screenshots here (no upload path from the VM); they are in the workspace's .context/shots/.
Tests
The tests go through the page (desktop-plans.test.ts). Ten of them fail without this change.
- The clamp is the document's floor, including on a 2000px-wide area where
mainstopped at 720. - The floor the stylesheet declares (folded: 423) is the one the drag holds to.
- Expand holds 90px past the greatest width, further than collapse's 80, and goes full screen past 160.
- Collapse still snaps past 200 and lets go past 224.
- Hysteresis works in both directions.
- In a narrow window, the drag holds 130px past the room and snaps past 160.
- The keyboard's End and arrow keys are held to the same room.
./scripts/check.sh exits 0. A first run timed out once in packages/voice/src/live-session-source.test.ts, which this PR doesn't touch; it passes 3/3 alone and the full re-run was green.
🤖 Generated with Claude Code