mirror of
https://github.com/anomalyco/opencode.git
synced 2026-11-13 19:46:16 +03:00
fix(app): put the sidebar channel icon under the macOS traffic lights (#57235)
Co-authored-by: Brendonovich <14191578+Brendonovich@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
0871812772
commit
e50f112667
@@ -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",
|
||||
|
||||
@@ -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 } }) {
|
||||
>
|
||||
<Show when={!windows()}>
|
||||
{/* Shares the session header's 48px center line. Without traffic lights or a channel
|
||||
icon, Home fills the start so the row doesn't leave an empty band. */}
|
||||
icon, Home fills the start so the row doesn't leave an empty band. With both, the
|
||||
channel icon goes under the traffic lights and the row grows only by what it needs. */}
|
||||
<div
|
||||
class="flex w-full shrink-0 gap-2"
|
||||
classList={{
|
||||
"items-start pt-2.5": homeInSidebarHeader(),
|
||||
"mb-2 h-12 items-center": !homeInSidebarHeader(),
|
||||
"mb-2 h-12 items-center":
|
||||
!homeInSidebarHeader() && !channelIndicatorBelowTrafficLights(),
|
||||
"mb-2 items-start": channelIndicatorBelowTrafficLights(),
|
||||
}}
|
||||
style={{
|
||||
"min-height": macVerticalTabs()
|
||||
@@ -799,23 +803,36 @@ export function Titlebar(props: { verticalTabs?: { mount?: HTMLElement } }) {
|
||||
<Show when={macTrafficLights()}>
|
||||
{/* The sidebar's 10px start padding already covers part of the traffic lights. */}
|
||||
<div
|
||||
class="shrink-0"
|
||||
style={{ width: `calc(${macTrafficLightsBaseWidth / zoom()}px - 10px)` }}
|
||||
aria-hidden="true"
|
||||
/>
|
||||
class="flex shrink-0"
|
||||
style={{
|
||||
width: `calc(${macTrafficLightsBaseWidth / zoom()}px - 10px)`,
|
||||
"padding-top": channelIndicatorBelowTrafficLights()
|
||||
? `${macTrafficLightsTopClearance / zoom()}px`
|
||||
: undefined,
|
||||
}}
|
||||
>
|
||||
<ChannelIndicator sidebar />
|
||||
</div>
|
||||
</Show>
|
||||
<Show
|
||||
when={homeInSidebarHeader()}
|
||||
fallback={
|
||||
<>
|
||||
<ChannelIndicator sidebar />
|
||||
<Show when={!macTrafficLights()}>
|
||||
<ChannelIndicator sidebar />
|
||||
</Show>
|
||||
<div class="flex-1" />
|
||||
</>
|
||||
}
|
||||
>
|
||||
<div class="min-w-0 flex-1">{homeButton(true)}</div>
|
||||
</Show>
|
||||
<SidebarToggle />
|
||||
<div
|
||||
class="flex shrink-0"
|
||||
classList={{ "mt-2.5": channelIndicatorBelowTrafficLights() }}
|
||||
>
|
||||
<SidebarToggle />
|
||||
</div>
|
||||
</div>
|
||||
</Show>
|
||||
<Show when={!homeInSidebarHeader()}>{homeButton(true)}</Show>
|
||||
|
||||
Reference in New Issue
Block a user