A tree view row cannot be styled: no border, no spacing, and a long file name gets middle-ellipsized in a narrow strip — which on a real project left "ClientDogSurger...nionBehaviour.cs" and hid the project text entirely. Drawing the rows means controlling all of it. - A coloured left border per project instead of a tinted icon, so the file icon slot is free and the name gets the width. The border uses var(--vscode-verticalTabs-projectN): VS Code injects every contributed theme colour into a webview, so overrides in colorCustomizations still apply and nothing is hardcoded. - The name is split into stem and extension, and only the stem ellipsizes, so ".cs" survives on a long name in a narrow view. - Configurable row spacing and border width, a rule under the pinned block, a dirty dot that the close button replaces on hover, italics for preview and for tabs that cannot be focused. - Selection, arrow/Home/End/Enter/Delete keys, middle-click to close, and an HTML context menu, since contributes.menus does not reach webview rows. - Clicking a webview row posts nothing rather than asking for an open that would silently do nothing. Actions moved to actions.ts so the wiring, the view and the tests share one implementation; extension.ts is now just registration. The per-row commands are gone — rows act through webview messages — and the palette keeps close / closeOthers / togglePin acting on the active editor. Verified in a browser harness at side-bar width: all twelve project colours resolve, rows stay a consistent 24px, and click, pin, close, middle-click, keyboard and both context-menu variants post the right intents. 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. Each row's icon is tinted by the project that contains the file — the nearest
.csproj/.fsproj/.vbproj,package.json,Cargo.toml,go.mod,pyproject.toml,pom.xmlorbuild.gradleabove it. 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.
- Sorting. Open order (matching the tab bar), by project so the colours run in blocks, or by file name. Pinned tabs stay on top.
- The project name beside the file, along with the directory when two files share a name.
Pinning is VS Code's own — this view just exposes it per row, and pinned tabs sort first.
Usage
| Action | How |
|---|---|
| Focus a tab | Click the row |
| Close | The × on hover, or the context menu |
| Pin / unpin | The pin icon on hover, or the context menu |
| Close others | Context menu — keeps pinned tabs |
| Change sorting | The view's … menu |
The list follows the active editor, so whatever you switch to is selected.
Settings
verticalTabs.order—open(default),project, ornameverticalTabs.pinnedFirst— list pinned tabs above the rest (defaulttrue)verticalTabs.showProject— show the project name beside the file (defaulttrue)verticalTabs.showDirectory— show the directory beside the file (defaulttrue)verticalTabs.colorByProject— tint each row's icon by project (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 eight project colours are theme colours (verticalTabs.project1 … project8, plus
verticalTabs.noProject), so you can override any of them 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, with a tooltip saying so, but clicking them does nothing.
- Pinning another tab focuses it first. VS Code can only pin the active editor, so pinning a row means opening it and then pinning. Clicking a row's pin icon therefore also switches to it.
- No drag to reorder. The list reflects VS Code's own tab order; it cannot rearrange it. 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. - The colour replaces the file-type icon. Each row shows a tinted dot instead of the usual
.cs/.jsonicon. SetverticalTabs.colorByProjecttofalseto get file icons back and keep the project name in the description. - The colour is on the row's icon, not its label. Labels get the theme's own colouring (including Git status), which an extension cannot override without also recolouring the Explorer.
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 commands, 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