Vertical Tabs Dock Toggle — Delivery Notes
The vertical Tabs navigator (ADR-0012) defaults to the right dock, but it’s sometimes wanted on the left. This adds a single tab-bar control to the Tabs pane that flips it right ⇄ left, keeping the width you were looking at. This note is the delivery write-up — what shipped and the two dock frictions it exposed.
Status
Implemented and verified live. In tranquil-automations (lib/tab-controls.js, lib/pane-controls.js).
| Piece | State |
|---|---|
tabs-toggle-dock control in the Tabs pane’s tab-bar cluster | ✅ |
| Direction-aware icon/title (shows the side it will move to) | ✅ |
| Dock width preserved across the flip | ✅ |
pane-controls supports function-valued icon/title | ✅ |
The behavior wanted
“Add a control to the Tabs pane that toggles its dock between left and right. Default stays right, but sometimes I want it on the left.” And, on first cut: “when flipping, retain the width — going left→right it’s quite narrow on the right.”
What shipped
Two owned files, no core edits:
- The control (
tab-controls.js) — a second item added to the existing Tabs-view registration (alongside “Close All Tabs”).toggleTabsDock()finds the live view, reads its current dock viapane.getContainer().getLocation(), andpane.moveItemToPane(view, targetDock.getActivePane(), …)into the opposite side dock, thenshow()s and activates it. The icon/title are functions of the current location: alayout-sidebar-leftglyph + “Move Tabs to left dock” while on the right, flipping tolayout-sidebar-rightwhile on the left. - Function-valued controls (
pane-controls.js) —renderClusternow evaluatesicon/titlewhen they’re functions (backward-compatible with the existing string defs), so the toggle reflects live state. The move re-renders both the source and target panes (item leaving / arriving), so the button updates to the correct direction immediately after each flip.
The gotchas
- Width collapsed to the preferred size on move. Removing the last item from a dock resets that
dock’s
sizetonull(dock.jshandleDidRemovePaneItem). The target dock, seeing a null size onhandleDidAddPaneItem, falls back togetInitialSize()— i.e. the item’sgetPreferredWidth()(220px) — so a wider left dock arrived narrow on the right. Fix: read the source dock’sstate.sizebefore the move and reapply it to the target dock after (targetDock.setState({ size })). Dock exposes no public size getter/setter, so this touchesstate/setStatedirectly — internal but stable, and not a core-file edit. - PaneContainer ≠ Dock.
pane.getContainer()returns thePaneContainer(which hasgetLocation()), not theDockthat ownsstate.size. The size read/write goes throughatom.workspace.getLeftDock()/getRightDock(), keyed off the location.
Deferred
- The control only renders in the center/left/right panes (
pane-controlsdoesn’t inject into the bottom dock), so a Tabs view dragged to the bottom won’t show the toggle. Out of scope — the toggle is a left/right affordance, and the default stays the right dock.