mirror of
https://github.com/NanmiCoder/claude-code-haha.git
synced 2026-10-10 03:43:11 +08:00
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.
This commit is contained in:
@@ -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-2').getAttribute('data-state')).toBe('completed')
|
||||||
expect(screen.getByTestId('agent-teams-canvas-task-3').getAttribute('data-state')).toBe('running')
|
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' }))
|
fireEvent.click(screen.getByRole('button', { name: 'Review history' }))
|
||||||
expect(screen.queryByTestId('agent-teams-live-controls')).toBeNull()
|
expect(screen.queryByTestId('agent-teams-live-controls')).toBeNull()
|
||||||
expect(screen.getByTestId('agent-teams-replay-controls')).toBeTruthy()
|
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
|
const timeline = screen.getByRole('slider', { name: 'Replay timeline · click to seek' }) as HTMLInputElement
|
||||||
expect(timeline.value).toBe('1000')
|
expect(timeline.value).toBe('1000')
|
||||||
|
|||||||
@@ -321,9 +321,12 @@ export function AgentTeamsWorkbench({ sessionId }: { sessionId: string }) {
|
|||||||
aria-label={t('agentTeams.title')}
|
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)]"
|
className="relative flex h-full min-h-0 w-full flex-col overflow-hidden bg-[var(--color-surface)] text-[var(--color-text-primary)]"
|
||||||
>
|
>
|
||||||
<header className="shrink-0 overflow-x-auto border-b border-[var(--color-border)] bg-[var(--color-surface-container-lowest)]">
|
{/* A narrow pane wraps the controls onto a row of their own instead of
|
||||||
<div className="flex min-w-[1180px] items-center gap-5 px-[18px] py-2.5">
|
scrolling the header sideways; the team block and counters stay on
|
||||||
<div className="min-w-[260px]">
|
the first row. Nothing in a control wraps, only hint text truncates. */}
|
||||||
|
<header className="shrink-0 border-b border-[var(--color-border)] bg-[var(--color-surface-container-lowest)]">
|
||||||
|
<div className="flex flex-wrap items-center gap-x-5 gap-y-2.5 px-[18px] py-2.5">
|
||||||
|
<div className="min-w-0 max-w-full">
|
||||||
<div className="text-[11px] font-semibold text-[var(--color-text-tertiary)]">
|
<div className="text-[11px] font-semibold text-[var(--color-text-tertiary)]">
|
||||||
Agent Teams · {t('agentTeams.sharedTaskList')}
|
Agent Teams · {t('agentTeams.sharedTaskList')}
|
||||||
</div>
|
</div>
|
||||||
@@ -340,7 +343,7 @@ export function AgentTeamsWorkbench({ sessionId }: { sessionId: string }) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex shrink-0 items-center gap-[18px] border-x border-[var(--color-border)] px-[18px]">
|
<div className="flex shrink-0 items-center gap-[18px] border-l border-[var(--color-border)] pl-[18px]">
|
||||||
<div className="min-w-[74px]">
|
<div className="min-w-[74px]">
|
||||||
<div className="text-[11px] font-semibold text-[var(--color-text-tertiary)]">
|
<div className="text-[11px] font-semibold text-[var(--color-text-tertiary)]">
|
||||||
{t('agentTeams.stats.phase')}
|
{t('agentTeams.stats.phase')}
|
||||||
@@ -359,7 +362,7 @@ export function AgentTeamsWorkbench({ sessionId }: { sessionId: string }) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{followingLive ? (
|
{followingLive ? (
|
||||||
<div data-testid="agent-teams-live-controls" className="flex min-w-0 flex-1 items-center gap-3.5">
|
<div data-testid="agent-teams-live-controls" className="flex min-w-0 flex-[1_1_480px] items-center gap-3.5">
|
||||||
<div className="flex shrink-0 items-center gap-1.5 rounded-full bg-[var(--color-info-container)] px-2.5 py-1">
|
<div className="flex shrink-0 items-center gap-1.5 rounded-full bg-[var(--color-info-container)] px-2.5 py-1">
|
||||||
<span className="agent-teams-live-dot h-1.5 w-1.5 rounded-full bg-[var(--color-info)]" aria-hidden="true" />
|
<span className="agent-teams-live-dot h-1.5 w-1.5 rounded-full bg-[var(--color-info)]" aria-hidden="true" />
|
||||||
<span className="whitespace-nowrap text-xs font-medium text-[var(--color-on-info-container)]">
|
<span className="whitespace-nowrap text-xs font-medium text-[var(--color-on-info-container)]">
|
||||||
@@ -369,7 +372,7 @@ export function AgentTeamsWorkbench({ sessionId }: { sessionId: string }) {
|
|||||||
<span className="min-w-0 flex-1 truncate text-xs text-[var(--color-text-secondary)]">
|
<span className="min-w-0 flex-1 truncate text-xs text-[var(--color-text-secondary)]">
|
||||||
{liveHint}
|
{liveHint}
|
||||||
</span>
|
</span>
|
||||||
<Button variant="secondary" size="sm" onClick={enterReplay}>
|
<Button variant="secondary" size="sm" className="shrink-0 whitespace-nowrap" onClick={enterReplay}>
|
||||||
{t('agentTeams.reviewHistory')}
|
{t('agentTeams.reviewHistory')}
|
||||||
</Button>
|
</Button>
|
||||||
<div className="shrink-0 border-l border-[var(--color-border)] pl-3.5">
|
<div className="shrink-0 border-l border-[var(--color-border)] pl-3.5">
|
||||||
@@ -380,11 +383,11 @@ export function AgentTeamsWorkbench({ sessionId }: { sessionId: string }) {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div data-testid="agent-teams-replay-controls" className="flex min-w-0 flex-1 items-center gap-3.5">
|
<div data-testid="agent-teams-replay-controls" className="flex min-w-0 flex-[1_1_560px] flex-wrap items-center gap-x-3.5 gap-y-2">
|
||||||
<Button
|
<Button
|
||||||
variant="primary"
|
variant="primary"
|
||||||
size="base"
|
size="base"
|
||||||
className="w-[86px]"
|
className="w-[86px] shrink-0 whitespace-nowrap"
|
||||||
icon={playing ? <Pause size={13} aria-hidden="true" /> : <Play size={13} aria-hidden="true" />}
|
icon={playing ? <Pause size={13} aria-hidden="true" /> : <Play size={13} aria-hidden="true" />}
|
||||||
onClick={togglePlayback}
|
onClick={togglePlayback}
|
||||||
>
|
>
|
||||||
@@ -419,10 +422,10 @@ export function AgentTeamsWorkbench({ sessionId }: { sessionId: string }) {
|
|||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</div>
|
</div>
|
||||||
<div className="min-w-[200px] flex-1">
|
<div className="min-w-[180px] flex-1">
|
||||||
<div className="mb-1 flex justify-between text-[11px] font-semibold text-[var(--color-text-tertiary)]">
|
<div className="mb-1 flex justify-between gap-2 text-[11px] font-semibold text-[var(--color-text-tertiary)]">
|
||||||
<span>{t('agentTeams.replay.timeline')}</span>
|
<span className="min-w-0 truncate">{t('agentTeams.replay.timeline')}</span>
|
||||||
<span className="font-mono tabular-nums">
|
<span className="shrink-0 whitespace-nowrap font-mono tabular-nums">
|
||||||
{formatDuration(cursorTime - startTime)} / {formatDuration(totalElapsed)}
|
{formatDuration(cursorTime - startTime)} / {formatDuration(totalElapsed)}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -472,6 +475,7 @@ export function AgentTeamsWorkbench({ sessionId }: { sessionId: string }) {
|
|||||||
<Button
|
<Button
|
||||||
variant="secondary"
|
variant="secondary"
|
||||||
size="sm"
|
size="sm"
|
||||||
|
className="shrink-0 whitespace-nowrap"
|
||||||
icon={<Radio size={12} aria-hidden="true" />}
|
icon={<Radio size={12} aria-hidden="true" />}
|
||||||
onClick={returnToLive}
|
onClick={returnToLive}
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user