From c1ec601c00cc85ce1388261817c25a1027783a01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=A8=8B=E5=BA=8F=E5=91=98=E9=98=BF=E6=B1=9F=28Relakkes?= =?UTF-8?q?=29?= Date: Thu, 8 Oct 2026 21:54:38 +0800 Subject: [PATCH] fix(desktop): wrap the Agent Teams header in narrow panes The header had a fixed 1180px minimum that scrolled sideways and let flex squeeze button labels into vertical stacks. The controls now wrap onto their own row, and buttons and timings never wrap. --- .../agentTeams/AgentTeamsWorkbench.test.tsx | 10 +++++++ .../agentTeams/AgentTeamsWorkbench.tsx | 28 +++++++++++-------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/desktop/src/components/agentTeams/AgentTeamsWorkbench.test.tsx b/desktop/src/components/agentTeams/AgentTeamsWorkbench.test.tsx index 1099f8eb..46f6c778 100644 --- a/desktop/src/components/agentTeams/AgentTeamsWorkbench.test.tsx +++ b/desktop/src/components/agentTeams/AgentTeamsWorkbench.test.tsx @@ -122,9 +122,19 @@ describe('AgentTeamsWorkbench', () => { expect(screen.getByTestId('agent-teams-canvas-task-2').getAttribute('data-state')).toBe('completed') expect(screen.getByTestId('agent-teams-canvas-task-3').getAttribute('data-state')).toBe('running') + // A narrow pane wraps the controls onto their own row rather than forcing + // a fixed-width header that scrolls sideways and squeezes button labels. + const headerRow = screen.getByTestId('agent-teams-live-controls').parentElement! + expect(headerRow.className).toContain('flex-wrap') + expect(headerRow.className).not.toMatch(/\bmin-w-\[\d+px\]/) + expect(headerRow.parentElement!.className).not.toContain('overflow-x-auto') + fireEvent.click(screen.getByRole('button', { name: 'Review history' })) expect(screen.queryByTestId('agent-teams-live-controls')).toBeNull() expect(screen.getByTestId('agent-teams-replay-controls')).toBeTruthy() + for (const name of [/^(Play|Pause|Replay)$/, 'Back to live']) { + expect(screen.getByRole('button', { name }).className).toMatch(/(?=.*\bshrink-0\b)(?=.*\bwhitespace-nowrap\b)/) + } const timeline = screen.getByRole('slider', { name: 'Replay timeline · click to seek' }) as HTMLInputElement expect(timeline.value).toBe('1000') diff --git a/desktop/src/components/agentTeams/AgentTeamsWorkbench.tsx b/desktop/src/components/agentTeams/AgentTeamsWorkbench.tsx index e3f94c94..1d04d376 100644 --- a/desktop/src/components/agentTeams/AgentTeamsWorkbench.tsx +++ b/desktop/src/components/agentTeams/AgentTeamsWorkbench.tsx @@ -321,9 +321,12 @@ export function AgentTeamsWorkbench({ sessionId }: { sessionId: string }) { aria-label={t('agentTeams.title')} className="relative flex h-full min-h-0 w-full flex-col overflow-hidden bg-[var(--color-surface)] text-[var(--color-text-primary)]" > -
-
-
+ {/* A narrow pane wraps the controls onto a row of their own instead of + scrolling the header sideways; the team block and counters stay on + the first row. Nothing in a control wraps, only hint text truncates. */} +
+
+
Agent Teams · {t('agentTeams.sharedTaskList')}
@@ -340,7 +343,7 @@ export function AgentTeamsWorkbench({ sessionId }: { sessionId: string }) {
-
+
{t('agentTeams.stats.phase')} @@ -359,7 +362,7 @@ export function AgentTeamsWorkbench({ sessionId }: { sessionId: string }) {
{followingLive ? ( -
+
) : ( -
+
-
-
- {t('agentTeams.replay.timeline')} - +
+
+ {t('agentTeams.replay.timeline')} + {formatDuration(cursorTime - startTime)} / {formatDuration(totalElapsed)}
@@ -472,6 +475,7 @@ export function AgentTeamsWorkbench({ sessionId }: { sessionId: string }) {