Docs

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 + .url reverse-map and the autoReveal/toggle in tranquil-config; the center-cycle commands in tranquil-automations; the ⌥⌘W close-and-trash, reopen-restore, and command/keymap in tranquil-browser; and the browser-tab drop-to-.url path in tranquil-drag-drop. Revert ctrl-tab/ctrl-shift-tab to the plain pane:show-next-item / pane:show-previous-item of ADR-0006. Keep the browser model’s filePath plumbing (the core .url open/save system depends on it) and the general file-tab drop-to-copy and entry copy/undo in tranquil-drag-drop (never part of ADR-0008).
  • Feature. A VerticalTabsView in tranquil-automations — a plain workspace item whose getDefaultLocation() 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 calls pane.activateItem(item) + pane.activate(); the close button calls pane.destroyItem. It re-renders off the center pane’s onDidAddItem/onDidRemoveItem/onDidMoveItem/ onDidChangeActiveItem and each item’s onDidChangeTitle/onDidChangeModified, and re-watches when the center’s active pane changes (center.observeActivePane). Visibility is driven by a boolean config tranquil-automations.showVerticalTabs (default off) — the settings checkbox and a tranquil-automations:toggle-vertical-tabs command both flip it, and an addOpener + 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 the atom.file-icons service (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’s getTitle(). Two supporting fixes landed in tranquil-browser: the model now persists title/favIcon in serialize() (they were dropped on restore), and the favicon handler no longer wiped model.favIcon to undefined.
  • 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), not inherit/rgba hacks.

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 .url bookmarks 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).