ADR-0012: Vertical tab list in the right dock
Status: Active · Date: 2026-07-21
Context
ADR-0008 tried to make the file tree behave like a browser’s tab
list: keep the tree selection in lockstep with the active tab, give browser .url bookmark tabs a
durable identity, close-a-tab-and-trash-its-bookmark, and drag-a-tab-onto-a-folder-to-save. It
worked, but it spread across five packages and leaned on tree-view internals in ways that are
fragile and not idiomatic for a browser-first editor (ADR-0002).
The underlying want is the browser one: see all the open tabs at once in a vertical list, the way Arc/Edge/Firefox put tabs down the side while content fills the main area. The right dock is the natural home for that list, with the editor/browser content staying in the center.
Decision
Remove ADR-0008 in full and add an opt-in vertical tab list in the right dock.
- Removal. Delete the tree-view sync patch +
.urlreverse-map and theautoReveal/toggle intranquil-config; the center-cycle commands intranquil-automations; the ⌥⌘W close-and-trash, reopen-restore, and command/keymap intranquil-browser; and the browser-tab drop-to-.urlpath intranquil-drag-drop. Revertctrl-tab/ctrl-shift-tabto the plainpane:show-next-item/pane:show-previous-itemof ADR-0006. Keep the browser model’sfilePathplumbing (the core.urlopen/save system depends on it) and the general file-tab drop-to-copy and entry copy/undo intranquil-drag-drop(never part of ADR-0008). - Feature. A
VerticalTabsViewintranquil-automations— a plain workspace item whosegetDefaultLocation()is'right'. It renders the center’s active pane’s items as a vertical list (<li class="tranquil-vertical-tab">with title, unsaved dot, hover close). Clicking a row callspane.activateItem(item)+pane.activate(); the close button callspane.destroyItem. It re-renders off the center pane’sonDidAddItem/onDidRemoveItem/onDidMoveItem/onDidChangeActiveItemand each item’sonDidChangeTitle/onDidChangeModified, and re-watches when the center’s active pane changes (center.observeActivePane). Visibility is driven by a boolean configtranquil-automations.showVerticalTabs(default off) — the settings checkbox and atranquil-automations:toggle-vertical-tabscommand both flip it, and anaddOpener+ deserializer let the panel dedupe by URI and restore across reloads. - Row content (as shipped). Each row shows an icon + label. Icon: the page favicon for
browser tabs (
item.favIcon), otherwise the tree-view file-type icon via theatom.file-iconsservice (rendered as a monochrome octicon, deliberately distinct from the tree’s colored codicons). Label: the browser tab’s live page<title>(read off the guest<webview>, cached per-URI and persisted so restored tabs show it before reload), else the item’sgetTitle(). Two supporting fixes landed intranquil-browser: the model now persiststitle/favIconinserialize()(they were dropped on restore), and the favicon handler no longer wipedmodel.favIcontoundefined. - Placement & visibility (as shipped).
getAllowedLocations()returns all four locations, so the panel drags to any dock or the center (right is only the default). Toggling on always reveals the dock — even one closed manually — and the command is visibility-aware (reveal if hidden, hide if shown). Colours come from the new ui-variables (ADR-0013), notinherit/rgbahacks.
Because it’s an ordinary dock item, none of the tabs package or other third-party code is touched
(never modify packages we don’t own).
Options considered
- Custom vertical tab-list view mirroring the center pane (chosen) — content stays center, the list is a side navigator, which is exactly the browser affordance asked for. Owned code only; a plain workspace item slots into the dock and restore machinery for free. Con: it re-derives tab state from workspace events (a small amount of view logic), and — by design — reflects the active center pane, so with a split it follows the focused side rather than showing every pane at once.
- Style the right dock’s own native tab bar vertically — a config-toggled body class + CSS on
.tab-bar[location="right"], no JS view. Rejected: it makes the right dock’s tabs vertical, not a navigator for the center; you’d have to move your editor/browser tabs into the dock, which isn’t what “list the main view’s tabs on the side” means. (This was built first and reverted.) - Always-on, no toggle — rejected: the ask was for an option; a persisted config + command is the right surface.
- Resurrect a tree-view-based list (ADR-0008 shape) — rejected: the complexity this ADR exists to remove.
Consequences
- Browser-native. A real vertical tab rail for the main view, the standard modern-browser affordance, without pressing the file tree into a tab-list role.
- Simpler than ADR-0008. One owned view + one config key, versus a five-package sync system.
- Theme-agnostic styling. The panel colours use
inherit+ neutral translucent overlays (the business themes don’t export ui-variables — see theme development), so it works across themes with no per-theme CSS to keep in sync. - Behaviour changes for ADR-0008 users. The tree no longer auto-follows the active tab; ⌥⌘W no
longer closes-and-trashes a bookmark; dragging a browser tab onto a folder no longer writes a
.url. Core.urlbookmarks still open/save; tree-view drag copy/move + undo are unchanged. - Re-evaluation triggers. If the “active pane only” behaviour is limiting under splits, extend the view to group all center panes; if drag-to-reorder in the list is wanted, add it (the list is ours, so no third-party constraints).