From e50f1126671a6bbca81e9c5d1b52472eacca7af3 Mon Sep 17 00:00:00 2001
From: "opencode-agent[bot]"
<219766164+opencode-agent[bot]@users.noreply.github.com>
Date: Tue, 20 Oct 2026 00:56:51 +0000
Subject: [PATCH] fix(app): put the sidebar channel icon under the macOS
traffic lights (#57235)
Co-authored-by: Brendonovich <14191578+Brendonovich@users.noreply.github.com>
---
packages/app/e2e/regression/tabs.spec.ts | 39 ++++++++++++++++++++
packages/app/src/shell/titlebar/titlebar.tsx | 33 +++++++++++++----
2 files changed, 64 insertions(+), 8 deletions(-)
diff --git a/packages/app/e2e/regression/tabs.spec.ts b/packages/app/e2e/regression/tabs.spec.ts
index 17908249d01..46d6ab7332a 100644
--- a/packages/app/e2e/regression/tabs.spec.ts
+++ b/packages/app/e2e/regression/tabs.spec.ts
@@ -463,6 +463,45 @@ for (const [window, fullscreen, start] of [
})
}
+// macOS 26 traffic lights sit 14px down and are 14px tall. With vertical tabs the channel icon goes below them, over
+// Home's icon. A fullscreen window has no traffic lights, so the icon stays in the header beside the sidebar toggle.
+for (const [window, fullscreen] of [
+ ["windowed", false],
+ ["fullscreen", true],
+] as const) {
+ test(`sidebar channel icon sits below the macOS traffic lights (${window})`, async ({ page }) => {
+ await mockWorkspace(page, {
+ name: "Tabs",
+ sessions: [a],
+ seed: { settings: { appearance: { tabLayout: "vertical" } } },
+ })
+ await page.goto(
+ `/e2e/utils/macos-window.html?${new URLSearchParams({ server: SERVER, route: "/", fullscreen: String(fullscreen) })}`,
+ )
+ const sidebar = page.locator('[data-slot="vertical-tabs-sidebar"]')
+ const indicator = sidebar.locator('[data-slot="channel-indicator"]')
+ await expect(indicator).toBeVisible()
+
+ const icon = await indicator.boundingBox()
+ const toggle = await sidebar.getByRole("button", { name: "Toggle sidebar", exact: true }).boundingBox()
+ const home = await sidebar.getByRole("button", { name: "Home", exact: true }).boundingBox()
+ const homeIcon = await sidebar.getByRole("button", { name: "Home", exact: true }).locator("svg").boundingBox()
+
+ if (!icon || !toggle || !home || !homeIcon) throw new Error("sidebar header has no bounding boxes")
+
+ if (fullscreen) {
+ expect(icon.y + icon.height / 2).toBe(toggle.y + toggle.height / 2)
+ return
+ }
+
+ expect(icon.y).toBeGreaterThan(14 + 14)
+ expect(icon.x + icon.width / 2).toBe(homeIcon.x + homeIcon.width / 2)
+ expect(icon.y + icon.height).toBeLessThan(home.y)
+ // The toggle keeps the session header's center line beside the icon.
+ expect(toggle.y + toggle.height / 2).toBe(32)
+ })
+}
+
test("vertical tab gaps hover and select the nearest row", async ({ page }) => {
await mockWorkspace(page, {
name: "Tabs",
diff --git a/packages/app/src/shell/titlebar/titlebar.tsx b/packages/app/src/shell/titlebar/titlebar.tsx
index c34d89014c8..4dcafa804a3 100644
--- a/packages/app/src/shell/titlebar/titlebar.tsx
+++ b/packages/app/src/shell/titlebar/titlebar.tsx
@@ -114,6 +114,7 @@ export function Titlebar(props: { verticalTabs?: { mount?: HTMLElement } }) {
const titlebarItems = useTitlebarItems()
const hideVerticalTitlebar = createMemo(() => !!props.verticalTabs && !windows())
const homeInSidebarHeader = () => !windows() && !macTrafficLights() && !channelIndicatorVisible
+ const channelIndicatorBelowTrafficLights = () => macTrafficLights() && channelIndicatorVisible
const back = () => {
const next = backPath(history)
@@ -782,12 +783,15 @@ export function Titlebar(props: { verticalTabs?: { mount?: HTMLElement } }) {
>