diff --git a/packages/ui/desktop/src/app.ts b/packages/ui/desktop/src/app.ts index c74acd94c3..d40ca4dcfa 100644 --- a/packages/ui/desktop/src/app.ts +++ b/packages/ui/desktop/src/app.ts @@ -666,7 +666,7 @@ function renderLiveTurn(): void { const label = row.querySelector('summary strong') if (label !== null) label.textContent = tool.title const statusEl = row.querySelector('summary span') - if (statusEl !== null) statusEl.textContent = tool.status === 'failed' ? t('chat.toolFailed') : t('chat.toolUse') + if (statusEl !== null) statusEl.textContent = tool.status === 'failed' ? t('chat.toolFailed') : verbForKind(state.liveToolMeta.get(tool.callId)?.kind) const body = row.querySelector('.activity-body pre') if (body !== null) body.textContent = tool.detail row.classList.toggle('failed', tool.status === 'failed') @@ -1088,7 +1088,7 @@ function renderInteractionDock(): void {
${request.kind === 'elicitation' ? `` : ''} ${request.options.map(option => ``).join('')} - + ${request.options.some(option => option.kind.startsWith('reject')) ? '' : ``}
`).join('') @@ -1170,7 +1170,10 @@ function liveToolTitle(target: TraceTarget): string | undefined { /** Verb label for a tool row: the streamed ACP kind beats the generic noun. */ function toolVerbLabel(target: TraceTarget): string { - const kind = liveToolMetaOf(target).kind + return verbForKind(liveToolMetaOf(target).kind) +} + +function verbForKind(kind: string | undefined): string { if (kind === 'read') return t('kind.verb.read') if (kind === 'edit') return t('kind.verb.edit') if (kind === 'delete') return t('kind.verb.delete') diff --git a/packages/ui/desktop/src/styles.css b/packages/ui/desktop/src/styles.css index 109bdfced3..b36c70f0f2 100644 --- a/packages/ui/desktop/src/styles.css +++ b/packages/ui/desktop/src/styles.css @@ -391,7 +391,8 @@ kbd { display: grid; min-width: 0; min-height: 0; - grid-template-rows: 58px auto minmax(0, 1fr) auto; + /* topbar / notice / canvas / interaction / queue / plan / composer */ + grid-template-rows: 58px auto minmax(0, 1fr) auto auto auto auto; background: var(--paper); } @@ -408,10 +409,22 @@ kbd { grid-row: 3; } -.composer { +#interactionDock { grid-row: 4; } +#queueDock { + grid-row: 5; +} + +#planDock { + grid-row: 6; +} + +.composer { + grid-row: 7; +} + .topbar { display: grid; grid-template-columns: minmax(220px, 1fr) auto auto; diff --git a/packages/ui/desktop/tests/renderer-regressions.spec.ts b/packages/ui/desktop/tests/renderer-regressions.spec.ts index 87779e7bc7..5a772cc9b2 100644 --- a/packages/ui/desktop/tests/renderer-regressions.spec.ts +++ b/packages/ui/desktop/tests/renderer-regressions.spec.ts @@ -41,10 +41,15 @@ describe('desktop live content', () => { }) describe('desktop shell layout', () => { - it('pins the composer to its intrinsic bottom row', async () => { + it('pins the docks and composer to their explicit bottom rows', async () => { const css = await readFile(new URL('../src/styles.css', import.meta.url), 'utf8') expect(css).toMatch(/\.session-canvas,\s*\.module-canvas\s*{\s*grid-row: 3;/) - expect(css).toMatch(/\.composer\s*{\s*grid-row: 4;/) + // Every dock needs an explicit row: auto placement once floated the queue + // to the top of the main pane. + expect(css).toMatch(/#interactionDock\s*{\s*grid-row: 4;/) + expect(css).toMatch(/#queueDock\s*{\s*grid-row: 5;/) + expect(css).toMatch(/#planDock\s*{\s*grid-row: 6;/) + expect(css).toMatch(/\.composer\s*{\s*grid-row: 7;/) }) it('does not launch Electron after a strict-port Vite failure', async () => {