From 37a03df7339ca6aaf4efa765820c8dd97f89281b Mon Sep 17 00:00:00 2001 From: NI0317 Date: Mon, 20 Jul 2026 10:58:21 +0800 Subject: [PATCH] fix(ui): pin dock rows, verb labels on live tools, dedupe reject Auto placement floated the new docks to the top of the main pane; every dock now owns an explicit grid row (and the layout regression guards them). Live tool rows use the streamed kind verb like persisted rows, and the approval card's fallback reject is omitted when the request already carries a reject option. --- packages/ui/desktop/src/app.ts | 9 ++++++--- packages/ui/desktop/src/styles.css | 17 +++++++++++++++-- .../desktop/tests/renderer-regressions.spec.ts | 9 +++++++-- 3 files changed, 28 insertions(+), 7 deletions(-) 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 () => {