fix(new-workspace): center agent selection in create dialog (#11020)

* fix(new-workspace): center agent selection in create dialog

Pin the Agent combobox mark to 14px, drop residual button padding, and
use a full-width min-w-0 trigger so icon, label, and chevron align with
Project/Name in the new worktree dialog.

* fix(new-workspace): optically align agent picker content

* fix(new-workspace): center selected agent content
This commit is contained in:
Neil 2026-07-27 18:11:40 -07:00 committed by GitHub
parent dc45f79465
commit edc6cc007d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 82 additions and 21 deletions

View File

@ -1421,7 +1421,7 @@ export default function NewWorkspaceComposerCard({
</div>
</div>
<div className="space-y-1" data-contextual-tour-target="workspace-creation-agent">
<div className="min-w-0 space-y-1" data-contextual-tour-target="workspace-creation-agent">
<div className="flex items-center justify-between gap-2">
<label className="text-xs font-medium text-muted-foreground">
{translate('auto.components.NewWorkspaceComposerCard.01d1e8f601', 'Agent')}
@ -1459,7 +1459,9 @@ export default function NewWorkspaceComposerCard({
onOpenManageAgents={onOpenAgentSettings}
defaultAgent={defaultTuiAgent}
onSetDefault={handleSetDefaultAgent}
triggerClassName="h-9 w-full border-input text-sm focus:border-ring focus:ring-[3px] focus:ring-ring/50"
// Why: match Project/Run-on — full-width form row, no 260px min that can overflow the dialog column.
allowNarrowTrigger
triggerClassName="h-9 w-full min-w-0 border-input text-sm focus:border-ring focus:ring-[3px] focus:ring-ring/50"
onTriggerEnter={createDisabled ? undefined : onCreate}
/>
</div>

View File

@ -21,6 +21,46 @@ describe('AgentCombobox', () => {
expect(markup).toContain('flex-1')
})
it('centers the selected agent mark and label inside a full-width form trigger', () => {
const markup = renderToStaticMarkup(
<AgentCombobox
agents={AGENT_CATALOG}
value="codex"
onValueChange={vi.fn()}
allowNarrowTrigger
triggerClassName="h-9 w-full min-w-0"
/>
)
expect(markup).toContain('Codex')
expect(markup).not.toContain('!min-w-[260px]')
expect(markup).toContain('min-w-0 w-full')
expect(markup).toContain('leading-none')
expect(markup).toContain('size-3.5 shrink-0')
expect(markup).not.toContain('translate-y')
// Why: React HTML-escapes `[`/`&` in class strings during static markup.
expect(markup).toContain('size-3.5!')
})
it('uses the same centered 14px layout for every agent mark', () => {
for (const agent of AGENT_CATALOG) {
const markup = renderToStaticMarkup(
<AgentCombobox
agents={AGENT_CATALOG}
value={agent.id}
onValueChange={vi.fn()}
allowNarrowTrigger
/>
)
expect(markup).toContain(agent.label)
expect(markup).toContain('size-3.5 shrink-0')
expect(markup).not.toContain('translate-y')
expect(markup).toContain('width="14"')
expect(markup).toContain('height="14"')
}
})
it('supports an Agent-only empty state without presenting a blank terminal', () => {
const markup = renderToStaticMarkup(
<AgentCombobox

View File

@ -69,6 +69,23 @@ type ItemRenderArgs = {
label: string
}
function AgentIconLabel({
icon,
label
}: {
icon: React.ReactNode
label: string
}): React.JSX.Element {
return (
<span className="inline-flex min-w-0 flex-1 items-center gap-1.5">
<span className="inline-flex size-3.5 shrink-0 items-center justify-center [&_img]:size-3.5 [&_svg]:size-3.5!">
{icon}
</span>
<span className="truncate leading-none">{label}</span>
</span>
)
}
function renderItem({
key,
itemValue,
@ -86,11 +103,10 @@ function renderItem({
onSelect={onSelect}
className="items-center gap-2 px-3 py-1.5"
>
<Check className={cn('size-4 text-foreground', isChecked ? 'opacity-100' : 'opacity-0')} />
<span className="inline-flex min-w-0 flex-1 items-center gap-1.5">
{icon}
<span className="truncate">{label}</span>
</span>
<Check
className={cn('size-4 shrink-0 text-foreground', isChecked ? 'opacity-100' : 'opacity-0')}
/>
<AgentIconLabel icon={icon} label={label} />
</CommandItem>
)
if (!onSetDefault) {
@ -268,7 +284,9 @@ export default function AgentCombobox({
)
return (
<div className="flex w-full items-center">
// Why: min-w-0 lets full-width form rows shrink; plain flex+items-center left the
// trigger free to overflow its dialog column and look misaligned with Project/Name.
<div className="min-w-0 w-full">
<Popover open={open} onOpenChange={handleOpenChange}>
<PopoverTrigger asChild>
<Button
@ -281,27 +299,28 @@ export default function AgentCombobox({
className={cn(
// Why: callers sometimes pass `min-w-0` for grid layouts, but
// the compact trigger still needs room for "GitHub Copilot".
'h-8 justify-between px-3 text-xs font-normal',
// py-0 clears the default size's py-2 so icon+label center in h-8/h-9.
'h-8 justify-between px-3 py-0 text-xs font-normal',
triggerClassName,
!allowNarrowTrigger && TRIGGER_MIN_WIDTH_CLASS
)}
data-agent-combobox-root="true"
>
{selectedAgent ? (
<span className="inline-flex min-w-0 flex-1 items-center gap-1.5">
<AgentIcon agent={selectedAgent.id} />
<span className="truncate">{selectedAgent.label}</span>
</span>
<AgentIconLabel
icon={<AgentIcon agent={selectedAgent.id} size={14} />}
label={selectedAgent.label}
/>
) : (
<span className="inline-flex min-w-0 flex-1 items-center gap-1.5">
<Terminal className="size-3.5" />
<span className="truncate">
{emptyLabel ??
translate('auto.components.agent.AgentCombobox.986f946354', 'Blank Terminal')}
</span>
</span>
<AgentIconLabel
icon={<Terminal className="size-3.5" />}
label={
emptyLabel ??
translate('auto.components.agent.AgentCombobox.986f946354', 'Blank Terminal')
}
/>
)}
<ChevronsUpDown className="size-3.5 opacity-50" />
<ChevronsUpDown className="size-3.5 shrink-0 opacity-50" />
</Button>
</PopoverTrigger>
<PopoverContent