diff --git a/apps/desktop/e2e/session-workbar.spec.ts b/apps/desktop/e2e/session-workbar.spec.ts index 22a6ae701d..c090b996f2 100644 --- a/apps/desktop/e2e/session-workbar.spec.ts +++ b/apps/desktop/e2e/session-workbar.spec.ts @@ -144,7 +144,7 @@ async function waitForCompanionForkId(page: Page, sourceSessionId: string) { } async function setRightWorkbarWidth(page: Page, width: number) { - const layoutOwner = page.locator('.maka-workbar-layout-vars'); + const layoutOwner = page.locator('.appFrame'); const workbar = page.locator('.maka-session-workbar[data-placement="right"]'); await expect(layoutOwner).toHaveCount(1); await expect(workbar).toBeVisible(); @@ -160,6 +160,40 @@ async function setRightWorkbarWidth(page: Page, width: number) { return workbar; } +test('a wide right workbar keeps a long session title and Share action outside the panel', async ({ + window: page, +}) => { + const { sessionId } = await createSession(page, 'create long title workbar session'); + const longTitle = + 'Investigate why the completed plan session title overlaps the token usage dashboard'; + await page.evaluate( + ({ id, title }) => window.maka.sessions.rename(id, title), + { id: sessionId, title: longTitle }, + ); + + const identity = page.locator('[data-maka-contract="titlebar-identity"]'); + const share = page.getByRole('button', { name: '分享此任务' }); + await expect(identity).toContainText('Investigate why the completed plan session title'); + await expect(share).toBeVisible(); + + await page.getByRole('button', { name: '打开用量追踪' }).click(); + const workbar = await setRightWorkbarWidth(page, 600); + await expect( + page.locator('[data-maka-contract="session-inspector"]'), + ).toBeVisible(); + + const [identityBox, workbarBox] = await Promise.all([ + identity.boundingBox(), + workbar.boundingBox(), + ]); + expect(identityBox).not.toBeNull(); + expect(workbarBox).not.toBeNull(); + expect(identityBox!.x + identityBox!.width).toBeLessThanOrEqual(workbarBox!.x); + + await share.click(); + await expect(page.getByText('分享任务', { exact: true })).toBeVisible(); +}); + test('narrow right workbar keeps launcher shortcuts and side-chat send button inside', async ({ window: page, }) => { diff --git a/apps/desktop/renderer-architecture.json b/apps/desktop/renderer-architecture.json index a163a5c3e0..acc7bd8ecd 100644 --- a/apps/desktop/renderer-architecture.json +++ b/apps/desktop/renderer-architecture.json @@ -899,7 +899,7 @@ "react": 1 }, "importSpecifiers": 124, - "nonTriviaTokens": 15588 + "nonTriviaTokens": 15573 }, "src/renderer/use-app-shell-composer-quotes.ts": { "importDeclarations": 2, diff --git a/apps/desktop/src/renderer/app-shell.tsx b/apps/desktop/src/renderer/app-shell.tsx index 8c8f20fa33..e3738afcb1 100644 --- a/apps/desktop/src/renderer/app-shell.tsx +++ b/apps/desktop/src/renderer/app-shell.tsx @@ -24,7 +24,6 @@ import { useMemo, useRef, useState, - type CSSProperties, type ComponentProps, type Dispatch, type SetStateAction, @@ -2673,13 +2672,7 @@ function AppShellContent({ `data-sidebar-state`. Writing both here would duplicate the constant; writing this one unconditionally would bury the other, since an inline custom property outranks any rule that redefines it. */ - style={ - sessionListCollapsed - ? undefined - : ({ - '--maka-sidenav-width': `${sessionListWidth}px`, - } as CSSProperties) - } + style={workbar.getFrameStyle(sessionListCollapsed, sessionListWidth)} > + ({ + '--maka-session-workbar-width': `${layout.workbarWidth}px`, + // The reserve assumes the only side placement is `right`; add a + // placement guard here if left-side workbars are introduced. + '--maka-titlebar-workbar-reserve': + input.available && !layout.workbarCollapsed + ? 'calc(var(--maka-session-workbar-width) + var(--agents-content-area-gap))' + : '0px', + ...(sidebarCollapsed ? {} : { '--maka-sidenav-width': `${sidebarWidth}px` }), + }) as CSSProperties, commands, LiveContextUsageProbe, selectors: { diff --git a/apps/desktop/src/renderer/features/workbar/ui/workbar-host.tsx b/apps/desktop/src/renderer/features/workbar/ui/workbar-host.tsx index 08af527931..2cce85524e 100644 --- a/apps/desktop/src/renderer/features/workbar/ui/workbar-host.tsx +++ b/apps/desktop/src/renderer/features/workbar/ui/workbar-host.tsx @@ -127,7 +127,6 @@ export function WorkbarHost({ model: props }: { model: WorkbarHostModel }) { const toast = useToast(); const copy = getShellCopy(locale).app; const style = { - '--maka-session-workbar-width': `${props.rightWidth}px`, '--maka-session-bottom-panel-height': `${props.bottomHeight}px`, } as CSSProperties; diff --git a/apps/desktop/src/renderer/styles/shell-layout.css b/apps/desktop/src/renderer/styles/shell-layout.css index ce6ea21dd8..98a2adf640 100644 --- a/apps/desktop/src/renderer/styles/shell-layout.css +++ b/apps/desktop/src/renderer/styles/shell-layout.css @@ -273,7 +273,10 @@ the OS reports (macOS: traffic lights on the left; Windows: caption buttons on the right; Linux: neither, so the design floor stands). */ padding-left: var(--maka-titlebar-gutter-left); - padding-right: calc(var(--space-6) + var(--maka-titlebar-overlay-right-width)); + padding-right: calc( + var(--space-6) + var(--maka-titlebar-overlay-right-width) + + var(--maka-titlebar-workbar-reserve, 0px) + ); -webkit-app-region: drag; /* Three columns, not a flex row, because the middle one has to line up with