On a real project the name lost the width fight and the trailing text read "MyGame.Runtime MyGame.Runtime" — the directory and the project were the same string, printed twice. - The detail text now has a shrink factor of 1000 against the name's 1, plus a 45% cap, so it gives up its width first and the name is the last thing to ellipsize. - A directory that already begins with the project name says everything the project name would, so only one of the two is shown. - verticalTabs.showDirectory became never / duplicates / always, defaulting to duplicates: width goes to a directory only when two open tabs share a file name, which is the usual reason to want it. Turning showProject off as well gives the name the whole row. - The trailing text is composed in the extension now rather than the webview, so the deduplication is unit-testable and there is one implementation. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Vertical Tabs
Your open editors as a flat vertical list, colour-coded by project. Built for working with the tab bar turned
off ("workbench.editor.showTabs": "none"), where a side list is the tab bar.
It shows up as a Tabs view in the Explorer — drag it wherever you want it, including the secondary side bar.
What it adds over the built-in Open Editors view
- A colour per project, as a border down the left of each row — the way Visual Studio marks them. The
project is the nearest
.asmdef,.csproj/.fsproj/.vbproj,package.json,Cargo.toml,go.mod,pyproject.toml,pom.xmlorbuild.gradleabove the file. The colour comes from a hash of the project name, so a project keeps the same colour across sessions and windows. - A flat list, not a tree. One row per open editor, no group nodes to expand.
- Names that stay readable in a narrow strip. The stem is ellipsized but the extension never is, so you
get
ClientDogSurgeryCompanionBeha… .csrather than losing the.cs. - Sorting. Open order (matching the tab bar), by project so the colours run in blocks, or by file name. Pinned tabs stay on top, with a rule under the pinned block.
- Room to breathe. Row spacing and border width are settings.
Pinning is VS Code's own — this view exposes it per row as a single toggle, and pinned tabs sort first.
Usage
| Action | How |
|---|---|
| Focus a tab | Click the row |
| Close | The × on hover, middle-click, or Delete |
| Pin / unpin | The pin icon on the left of the row — one button, filled when pinned |
| Close others | Right-click → Close Others — keeps pinned tabs |
| Copy path, reveal in Explorer | Right-click |
| Move around | Arrow keys, Home, End, Enter to open |
| Change sorting | The view's … menu |
The list follows the active editor, so whatever you switch to is selected. An unsaved file shows a dot, which the close button replaces on hover.
Settings
verticalTabs.order—open(default),project, ornameverticalTabs.pinnedFirst— list pinned tabs above the rest (defaulttrue)verticalTabs.colorByProject— colour each row's left border by project (defaulttrue)verticalTabs.borderWidth— width of that border in pixels (default3)verticalTabs.rowSpacing— pixels between rows (default2)verticalTabs.showProject— also show the project name as text (defaulttrue)verticalTabs.showDirectory— also show the directory as text (defaulttrue)verticalTabs.allGroups— list every editor group, not just the active one (defaulttrue)verticalTabs.projectFiles— file names or extensions that mark a project root
The twelve project colours are theme colours (verticalTabs.project1 … project12, plus
verticalTabs.noProject), so you can pin a project to a specific colour in workbench.colorCustomizations.
Known limitations
- Webview tabs cannot be focused from the list. There is no API to activate an arbitrary tab; a file-backed tab is focused by re-opening its resource, which webviews (Settings, Keyboard Shortcuts, Markdown preview, extension panels) do not have. They are listed in italics, with a tooltip saying so, and clicking does nothing rather than pretending.
- Pinning another tab focuses it first. VS Code can only pin the active editor, so the pin button also switches to that tab.
- No drag to reorder. The list reflects VS Code's own tab order. Note that VS Code moves a pinned tab to
the front of its group, so
openorder shows pinned tabs first regardless ofverticalTabs.pinnedFirst— that setting only changes theprojectandnameorders. - No file-type icons. The row shows the project border instead. Adding icons back would mean bundling an icon set, since a webview cannot reach the active file-icon theme.
- Rows are drawn rather than native, so they do not pick up list styling from every theme the way a tree view would, and there is no native drag-and-drop.
Tests
npm test launches VS Code with all other extensions disabled on a multi-project folder, opens editors, and
asserts on the resulting list — projects resolved, ordering, pinning through the real actions, diff tabs
reporting their modified side, and webview tabs correctly reporting that they cannot be activated.
Point it at your own multi-project folder with VERTICAL_TABS_TEST_FOLDER:
VERTICAL_TABS_TEST_FOLDER=/path/to/solution npm test
The rendering itself is checked in a browser harness at side-bar width, driving the same media/tabs.js with
stub tab data.