feat(tab-group): make the split pane landing rows outline buttons (#40469)

This commit is contained in:
Kelvin Amoaba
2026-11-09 20:26:57 +00:00
committed by GitHub
parent 3a8b100f92
commit c66199ab94
3 changed files with 48 additions and 45 deletions
@@ -23,12 +23,9 @@ import {
ensureSimulatorTab,
getSimulatorTabForWorktree
} from '@/lib/simulator/tabs/ensure-simulator-tab'
import { Button } from '@/components/ui/button'
import { SplitPaneLandingAgentRow } from './SplitPaneLandingAgentRow'
import {
LANDING_ROW_CLASS,
LandingRowShortcut,
moveLandingRowFocus
} from './split-pane-landing-row'
import { LandingRowLabel, LandingRowShortcut, moveLandingRowFocus } from './split-pane-landing-row'
/** Fills an empty split pane so the user picks what opens there; each action creates into this group. */
export function SplitPaneLanding({
@@ -142,12 +139,12 @@ export function SplitPaneLanding({
return (
<div className="absolute inset-0 overflow-auto scrollbar-sleek bg-background">
<div className="mx-auto flex min-h-full w-full max-w-sm flex-col justify-center px-4 py-10">
<div className="mb-3 px-2.5 text-sm text-muted-foreground">
<div className="mb-3 text-sm text-muted-foreground">
{t('components.tabGroup.splitPaneLanding.heading', 'Open in this pane')}
</div>
<div
ref={listRef}
className="flex flex-col gap-1"
className="flex flex-col gap-2"
onKeyDown={(event) => moveLandingRowFocus(event, listRef.current)}
>
<SplitPaneLandingAgentRow
@@ -160,7 +157,7 @@ export function SplitPaneLanding({
))}
{canReopen ? (
<>
<div className="mx-2.5 my-1.5 h-px bg-border" />
<div className="my-1 h-px bg-border" />
<LandingRowButton
row={{
id: 'reopen',
@@ -177,13 +174,17 @@ export function SplitPaneLanding({
) : null}
</div>
{onClosePane ? (
<button
<Button
type="button"
className="mt-5 self-center rounded-md px-2.5 py-1 text-xs text-muted-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
variant="ghost"
size="sm"
className="mt-4 self-center"
onClick={onClosePane}
>
{t('components.tabGroup.splitPaneLanding.closePane', 'Close pane')}
</button>
<span className="text-muted-foreground">
{t('components.tabGroup.splitPaneLanding.closePane', 'Close pane')}
</span>
</Button>
) : null}
</div>
</div>
@@ -201,10 +202,17 @@ type LandingRow = {
function LandingRowButton({ row }: { row: LandingRow }): React.JSX.Element {
const Icon = row.icon
return (
<button type="button" data-landing-row className={LANDING_ROW_CLASS} onClick={row.onSelect}>
<Icon className="size-4 text-muted-foreground" />
<span className="min-w-0 flex-1 truncate text-left">{row.label}</span>
<Button
type="button"
variant="outline"
size="lg"
data-landing-row
className="w-full justify-start"
onClick={row.onSelect}
>
<Icon className="text-muted-foreground" />
<LandingRowLabel label={row.label} />
<LandingRowShortcut shortcut={row.shortcut} />
</button>
</Button>
)
}
@@ -2,7 +2,8 @@ import { Bot, ChevronDown } from 'lucide-react'
import { useAppStore } from '../../store'
import { useShortcutKeyDetails } from '@/hooks/useShortcutLabel'
import { useTranslate } from '@/i18n/use-translate'
import { cn } from '@/lib/utils'
import { Button } from '@/components/ui/button'
import { ButtonGroup } from '@/components/ui/button-group'
import { getAgentCatalog } from '@/lib/agent-catalog/agent-catalog'
import { AgentIcon } from '@/components/agent/icons/AgentIcon'
import { focusTerminalTabSurface } from '@/lib/focus-terminal-tab-surface'
@@ -18,9 +19,9 @@ import {
resolveTerminalAgentTabShortcut
} from '../terminal-agent-tab-shortcut'
import { launchAgentTabShortcut } from '../agent-tab-shortcut-launch'
import { LANDING_ROW_CLASS, LandingRowShortcut } from './split-pane-landing-row'
import { LandingRowLabel, LandingRowShortcut } from './split-pane-landing-row'
/** The default agent as one row; the chevron opens the + menu's agent list for any other. */
/** The default agent as a split button; the chevron opens the + menu's agent list for any other. */
export function SplitPaneLandingAgentRow({
worktreeId,
groupId,
@@ -59,36 +60,32 @@ export function SplitPaneLandingAgentRow({
}
return (
// Why: a stretched button keeps the row one click target while the chevron stays its own button.
<div
className={cn(
LANDING_ROW_CLASS,
'relative has-[[data-landing-row]:focus-visible]:bg-accent has-[[data-landing-row]:focus-visible]:text-accent-foreground'
)}
>
<button
<ButtonGroup className="w-full">
<Button
type="button"
variant="outline"
size="lg"
data-landing-row
aria-label={label}
className="absolute inset-0 rounded-md focus-visible:outline-none"
className="min-w-0 flex-1 justify-start"
onClick={launchDefault}
autoFocus={autoFocus}
/>
<span className="pointer-events-none flex text-muted-foreground">
{defaultAgent ? <AgentIcon agent={defaultAgent} size={16} /> : <Bot className="size-4" />}
</span>
<span className="pointer-events-none min-w-0 truncate">{label}</span>
>
{defaultAgent ? <AgentIcon agent={defaultAgent} size={16} /> : <Bot />}
<LandingRowLabel label={label} />
<LandingRowShortcut shortcut={shortcut} />
</Button>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<button
<Button
type="button"
variant="outline"
size="icon-lg"
aria-label={t('components.tabGroup.splitPaneLanding.chooseAgent', 'Choose agent')}
className="relative -ml-1.5 flex size-6 items-center justify-center rounded text-muted-foreground transition-colors hover:bg-foreground/10 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring data-[state=open]:bg-foreground/10 data-[state=open]:text-foreground"
>
<ChevronDown className="size-3.5" />
</button>
<ChevronDown className="text-muted-foreground" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="start" sideOffset={6} className="w-64">
<DropdownMenuContent align="end" sideOffset={6} className="w-64">
<QuickLaunchAgentMenuItems
worktreeId={worktreeId}
groupId={groupId}
@@ -96,10 +93,7 @@ export function SplitPaneLandingAgentRow({
/>
</DropdownMenuContent>
</DropdownMenu>
<span className="pointer-events-none ml-auto flex">
<LandingRowShortcut shortcut={shortcut} />
</span>
</div>
</ButtonGroup>
)
}
@@ -1,8 +1,9 @@
import type { ShortcutKeyComboDetails } from '@/hooks/useShortcutLabel'
import { ShortcutKeyCombo } from '../ShortcutKeyCombo'
export const LANDING_ROW_CLASS =
'flex h-9 w-full items-center gap-3 rounded-md px-2.5 text-sm text-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground focus-visible:outline-none'
export function LandingRowLabel({ label }: { label: string }): React.JSX.Element {
return <span className="min-w-0 flex-1 truncate text-left">{label}</span>
}
export function LandingRowShortcut({
shortcut