diff --git a/src/browser/components/TitleBar.tsx b/src/browser/components/TitleBar.tsx index 7c75bebeec..69ac445044 100644 --- a/src/browser/components/TitleBar.tsx +++ b/src/browser/components/TitleBar.tsx @@ -262,7 +262,13 @@ export function TitleBar() { )} style={leftInset > 0 ? { paddingLeft: leftInset } : undefined} > -
+
0 ? "flex-col" : "items-center gap-2", + isDesktop && "titlebar-no-drag" + )} + >
-
+
0 ? "h-3 w-[26px]" : "h-4 w-[35px]" + )} + > 0 && "-translate-y-px")} + className={cn("block h-full w-full", leftInset > 0 || "-translate-y-px")} /> {showUpdateShimmer && (
)}
-
+
0 ? "h-3 w-3" : "h-3.5 w-3.5" + )} + > {updateBadgeIcon}
@@ -301,7 +317,12 @@ export function TitleBar() { -
+
0 ? "text-[10px]" : "text-xs" + )} + > {gitDescribe ?? "(dev)"}
diff --git a/src/browser/stories/App.titlebar.stories.tsx b/src/browser/stories/App.titlebar.stories.tsx index 253378a632..2bb922f62d 100644 --- a/src/browser/stories/App.titlebar.stories.tsx +++ b/src/browser/stories/App.titlebar.stories.tsx @@ -1,109 +1,55 @@ /** - * Workspace titlebar / header stories + * Title bar stories - demonstrates title bar layout variants */ +import React from "react"; import { appMeta, AppWithMocks, type AppStory } from "./meta.js"; -import { - NOW, - createWorkspace, - groupWorkspacesByProject, - type GitStatusFixture, -} from "./mockFactory"; -import { createGitStatusExecutor, expandProjects, selectWorkspace } from "./storyHelpers"; -import { GIT_STATUS_INDICATOR_MODE_KEY } from "@/common/constants/storage"; -import { within, userEvent, waitFor } from "@storybook/test"; - import { createMockORPCClient } from "@/browser/stories/mocks/orpc"; export default { ...appMeta, - title: "App/Titlebar", + title: "App/TitleBar", }; /** - * Git status tooltip in workspace header - verifies alignment is near the indicator. - * The header uses tooltipPosition="bottom" which requires align="start" to stay anchored. + * macOS desktop mode with traffic lights inset. + * Logo is stacked above version to fit in constrained space. */ -export const GitStatusTooltip: AppStory = { +export const MacOSDesktop: AppStory = { + decorators: [ + (Story) => { + // Save and restore window.api to prevent leaking to other stories + const originalApiRef = React.useRef(window.api); + window.api = { + platform: "darwin", + versions: { + node: "20.0.0", + chrome: "120.0.0", + electron: "28.0.0", + }, + // This function's presence triggers isDesktopMode() → true + getIsRosetta: () => Promise.resolve(false), + }; + + // Cleanup on unmount + React.useEffect(() => { + const savedApi = originalApiRef.current; + return () => { + window.api = savedApi; + }; + }, []); + + return ; + }, + ], render: () => ( { - window.localStorage.setItem(GIT_STATUS_INDICATOR_MODE_KEY, JSON.stringify("line-delta")); - - const workspaces = [ - createWorkspace({ - id: "ws-active", - name: "feature/tooltip-test", - projectName: "my-app", - createdAt: new Date(NOW - 3600000).toISOString(), - }), - ]; - - const gitStatus = new Map([ - [ - "ws-active", - { - ahead: 3, - behind: 2, - dirty: 5, - outgoingAdditions: 150, - outgoingDeletions: 30, - headCommit: "WIP: Testing tooltip alignment", - }, - ], - ]); - - // Select workspace so header is visible - selectWorkspace(workspaces[0]); - expandProjects(["/home/user/projects/my-app"]); - - return createMockORPCClient({ - projects: groupWorkspacesByProject(workspaces), - workspaces, - executeBash: createGitStatusExecutor(gitStatus), - }); - }} + setup={() => + createMockORPCClient({ + projects: new Map(), + workspaces: [], + }) + } /> ), - play: async ({ canvasElement }: { canvasElement: HTMLElement }) => { - const canvas = within(canvasElement); - - // Wait for the workspace header to render with git status - await waitFor( - () => { - canvas.getByTestId("workspace-header"); - }, - { timeout: 5000 } - ); - - // Wait for git status to appear in the header specifically - const header = canvas.getByTestId("workspace-header"); - await waitFor( - () => { - within(header).getByText("+150"); - }, - { timeout: 5000 } - ); - - // Hover over the git status indicator in the header (not the sidebar) - const plusIndicator = within(header).getByText("+150"); - await userEvent.hover(plusIndicator); - - // Wait for tooltip to appear with correct alignment (portaled with data-state="open") - // The key fix: data-align="start" anchors tooltip near the indicator (not "center") - await waitFor( - () => { - const tooltip = document.body.querySelector( - '.bg-modal-bg[data-state="open"][data-align="start"]' - ); - if (!tooltip) throw new Error("git status tooltip not visible with align=start"); - // Verify tooltip has expected structure - within(tooltip).getByText("Divergence:"); - }, - { timeout: 5000 } - ); - - // Double-RAF to ensure layout is stable after async rendering - await new Promise((r) => requestAnimationFrame(() => requestAnimationFrame(r))); - }, };