fix: cluster repository launch chips

The composer context rail should read as one compact group, not three stretched controls. This change removes flex growth from the repository picker, caps branch width by content, softens the active worktree state, and removes hover borders that made secondary state controls look primary.

Constraint: Keep the existing composer and session layout unchanged.
Rejected: Use a prominent active outline for worktree | it made the state look like the primary action.
Confidence: high
Scope-risk: narrow
Directive: Keep this rail content-sized; long names should truncate inside chips instead of spreading across the bar.
Tested: cd desktop && bun run test -- --run src/components/shared/DirectoryPicker.test.tsx src/components/chat/ChatInput.test.tsx src/pages/EmptySession.test.tsx
Tested: bun run check:desktop
Tested: agent-browser desktop screenshot /tmp/cc-haha-repo-controls-compact-worktree-active-final.png and mobile overflow check /tmp/cc-haha-repo-controls-compact-mobile-final.png
Not-tested: Native Tauri packaged window visual check
This commit is contained in:
程序员阿江(Relakkes) 2026-05-07 18:40:25 +08:00
parent 3606531f7e
commit ca4900ed0c
3 changed files with 12 additions and 9 deletions

View File

@ -88,8 +88,11 @@ describe('DirectoryPicker', () => {
const trigger = screen.getByRole('button')
const label = screen.getByText(longProjectName)
const triggerClasses = trigger.className.split(/\s+/)
expect(trigger).toHaveAttribute('title', longPath)
expect(trigger.className).toContain('w-full')
expect(triggerClasses).toContain('max-w-full')
expect(triggerClasses).not.toContain('w-full')
expect(trigger.parentElement?.className).toContain('max-w-[320px]')
expect(label.className).toContain('truncate')
})

View File

@ -150,14 +150,14 @@ export function DirectoryPicker({ value, onChange, variant = 'chip', isGitProjec
const selectedLabel = selectedProject?.repoName || selectedProject?.projectName || projectNameFromPath(value)
const showGitIcon = selectedProject?.isGit || isGitProject
const triggerClassName = isWorkbar
? 'flex h-9 w-full min-w-0 items-center gap-1.5 rounded-[7px] border border-transparent px-2.5 text-[13px] font-medium leading-none text-[var(--color-text-secondary)] transition-colors hover:border-[var(--color-border)] hover:bg-[var(--color-surface-container-lowest)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-brand)]/35'
? 'inline-flex h-9 max-w-full min-w-0 items-center gap-1.5 rounded-[7px] border border-transparent px-2.5 text-[13px] font-medium leading-none text-[var(--color-text-secondary)] transition-colors hover:bg-[var(--color-surface-container-lowest)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-brand)]/35'
: 'flex items-center gap-2 px-3 py-1.5 bg-[var(--color-surface-container-low)] hover:bg-[var(--color-surface-hover)] rounded-full text-xs transition-colors border border-[var(--color-border)]'
const emptyTriggerClassName = isWorkbar
? 'flex h-9 min-w-0 items-center gap-1.5 rounded-[7px] border border-transparent px-2.5 text-[13px] font-medium leading-none text-[var(--color-text-secondary)] transition-colors hover:border-[var(--color-border)] hover:bg-[var(--color-surface-container-lowest)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-brand)]/35'
? 'flex h-9 min-w-0 items-center gap-1.5 rounded-[7px] border border-transparent px-2.5 text-[13px] font-medium leading-none text-[var(--color-text-secondary)] transition-colors hover:bg-[var(--color-surface-container-lowest)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-brand)]/35'
: 'flex items-center gap-2 text-xs text-[var(--color-text-tertiary)] hover:text-[var(--color-text-secondary)] transition-colors'
return (
<div ref={ref} className={isWorkbar ? 'relative min-w-0 flex-[1_1_220px] max-w-[360px]' : 'relative'}>
<div ref={ref} className={isWorkbar ? 'relative min-w-0 max-w-[320px] shrink' : 'relative'}>
{/* Trigger — shows selected project chip or placeholder */}
{value ? (
<button

View File

@ -257,11 +257,11 @@ export function RepositoryLaunchControls({
}, [isLaunchReady, onLaunchReadyChange])
const worktreeLabel = useWorktree ? t('repoLaunch.worktreeIsolated') : t('repoLaunch.worktreeCurrent')
const workbarButtonClassName = 'group inline-flex h-9 min-w-0 items-center gap-1.5 rounded-[7px] border border-transparent px-2.5 text-[13px] font-medium leading-none text-[var(--color-text-secondary)] transition-colors hover:border-[var(--color-border)] hover:bg-[var(--color-surface-container-lowest)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-brand)]/35 disabled:cursor-not-allowed disabled:opacity-50'
const workbarButtonClassName = 'group inline-flex h-9 max-w-full min-w-0 items-center gap-1.5 rounded-[7px] border border-transparent px-2.5 text-[13px] font-medium leading-none text-[var(--color-text-secondary)] transition-colors hover:bg-[var(--color-surface-container-lowest)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-brand)]/35 disabled:cursor-not-allowed disabled:opacity-50'
return (
<div ref={rootRef} className="flex min-w-0 flex-col gap-2">
<div className="flex min-h-[48px] min-w-0 flex-wrap items-center gap-x-2 gap-y-1 rounded-b-xl border-t border-[var(--color-border-separator)] bg-[var(--color-surface-container-low)] px-4 py-2 shadow-[inset_0_1px_0_rgba(255,255,255,0.45)]">
<div className="flex min-h-[48px] min-w-0 flex-wrap items-center justify-start gap-x-1.5 gap-y-1 rounded-b-xl border-t border-[var(--color-border-separator)] bg-[var(--color-surface-container-low)] px-4 py-2 shadow-[inset_0_1px_0_rgba(255,255,255,0.45)]">
<DirectoryPicker value={workDir} onChange={onWorkDirChange} variant="workbar" isGitProject={isGitReady} />
{loading && workDir && (
@ -273,7 +273,7 @@ export function RepositoryLaunchControls({
{isGitReady && (
<>
<span className="hidden h-5 w-px shrink-0 bg-[var(--color-border-separator)] sm:block" aria-hidden="true" />
<span className="hidden h-4 w-px shrink-0 bg-[var(--color-border-separator)] opacity-70 sm:block" aria-hidden="true" />
<button
ref={branchButtonRef}
type="button"
@ -286,7 +286,7 @@ export function RepositoryLaunchControls({
setBranchMenuOpen((prev) => !prev)
setBranchFilter('')
}}
className={`${workbarButtonClassName} flex-[0_1_260px]`}
className={`${workbarButtonClassName} max-w-[260px]`}
>
<GitBranch size={17} className="shrink-0 text-[var(--color-text-tertiary)] group-hover:text-[var(--color-text-secondary)]" />
<span className="min-w-0 flex-1 truncate text-[var(--color-text-primary)]">
@ -304,7 +304,7 @@ export function RepositoryLaunchControls({
onClick={() => onUseWorktreeChange(!useWorktree)}
className={`${workbarButtonClassName} ${
useWorktree
? 'border-[var(--color-border-focus)] bg-[var(--color-surface-container-lowest)] text-[var(--color-text-primary)] shadow-[inset_0_0_0_1px_var(--color-border-focus)]'
? 'bg-[var(--color-surface-container-lowest)] text-[var(--color-text-primary)]'
: ''
}`}
>