From d304171d7ceeaa38aad6ff32d735e0d4c90b5392 Mon Sep 17 00:00:00 2001 From: Miguel Palhas Date: Tue, 1 Sep 2026 09:48:15 +0100 Subject: [PATCH] feat(maestro): hide tab bar when a single tab The bar has nothing to switch between with one tab, so it is pure chrome. It reappears as soon as a second tab exists; spawn already opens its own tab, so the "+" button stays reachable. --- web/src/multiview.test.ts | 35 +++++++++++++++++++++++++++++++++++ web/src/multiview.ts | 4 ++++ web/src/styles.css | 3 ++- 3 files changed, 41 insertions(+), 1 deletion(-) diff --git a/web/src/multiview.test.ts b/web/src/multiview.test.ts index 4e9a8de..113347f 100644 --- a/web/src/multiview.test.ts +++ b/web/src/multiview.test.ts @@ -523,3 +523,38 @@ describe("multiview mobile single pane", () => { expect(mv.el.classList.contains("mv-mobile-solo")).toBe(true); }); }); + +describe("multiview solo tab bar", () => { + beforeEach(() => { + stubFetch(); + document.body.replaceChildren(); + }); + + afterEach(() => { + vi.unstubAllGlobals(); + }); + + it("hides the tab bar while only one tab exists", () => { + const layout = emptyLayout(); + const tab = layout.tabs[0]; + tab.focusedLeafId = splitLeaf(tab, "", "s1", "row", true); + const mv = makeMv(layout); + document.body.appendChild(mv.el); + mv.render(); + + expect(mv.el.classList.contains("mv-solo-tab")).toBe(true); + }); + + it("shows the tab bar again once a second tab appears", () => { + const layout = emptyLayout(); + const first = layout.tabs[0]; + first.focusedLeafId = splitLeaf(first, "", "s1", "row", true); + const second = addTab(layout); + second.focusedLeafId = splitLeaf(second, "", "s2", "row", true); + const mv = makeMv(layout); + document.body.appendChild(mv.el); + mv.render(); + + expect(mv.el.classList.contains("mv-solo-tab")).toBe(false); + }); +}); diff --git a/web/src/multiview.ts b/web/src/multiview.ts index 1408a05..17219ee 100644 --- a/web/src/multiview.ts +++ b/web/src/multiview.ts @@ -472,6 +472,10 @@ export function createMultiView(opts: MultiViewOptions): MultiView { // Mobile: the tab bar is a second navigation surface we don't want, so CSS // collapses it; the header ☰ keeps the sidebar drawer reachable. el.classList.toggle("mv-mobile-solo", isMobile); + // A lone tab has nothing to switch between, so the bar is only a strip of + // chrome; CSS hides it until a second tab exists. Spawning still opens its + // own tab (#100), which brings the bar back with the "+" button on it. + el.classList.toggle("mv-solo-tab", layout.tabs.length === 1); if (!tab.root) { pruneForms(tab); diff --git a/web/src/styles.css b/web/src/styles.css index d73701f..e6e98e5 100644 --- a/web/src/styles.css +++ b/web/src/styles.css @@ -2204,7 +2204,8 @@ input.leaf-rename:focus { } /* Mobile: the tab bar is a second navigation surface — collapse it (a floating ☰ inside the pane keeps the sidebar drawer reachable). */ -.mv-mobile-solo > .mv-tabs { +.mv-mobile-solo > .mv-tabs, +.mv-solo-tab > .mv-tabs { display: none; }