Scope worktree sidebar under dedicated `--worktree-sidebar` color tokens (#4845)

* Use a distinct background token for the worktree sidebar panel

- Adds `--worktree-sidebar` and `--worktree-sidebar-foreground` CSS tokens (light: #f5f5f5, dark: #212121) so the sidebar can be visually lighter than the default `--sidebar` value
- Applies `bg-worktree-sidebar` to the sidebar container

* Lighten worktree sidebar and scope its color tokens under `--worktree-si

- Dark mode panel lifted from `#212121` to `#2a2a2a` so it reads clearly above the `#0a0a0a` canvas.
- Added `--worktree-sidebar-accent`, `--worktree-sidebar-border`, and `--worktree-sidebar-ring` tokens in both color schemes.
- Migrated all sidebar components from shared `sidebar-*` tokens to the scoped `worktree-sidebar-*` tokens, preventing bleed when the two layers diverge.

* Use worktree-sidebar tokens in settings sidebar instead of generic theme

- Replaces `bg-accent`, `text-muted-foreground`, `border-border/50`, and `bg-card/40` with dedicated worktree-sidebar CSS custom properties
- Enables independent styling of the settings sidebar separate from the main panel theme
This commit is contained in:
Jinjing 2026-06-07 18:01:45 -07:00 committed by GitHub
parent 76cb846d68
commit 1826609215
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 118 additions and 80 deletions

View File

@ -52,6 +52,12 @@
--color-chart-5: var(--chart-5);
--color-sidebar: var(--sidebar);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-worktree-sidebar: var(--worktree-sidebar);
--color-worktree-sidebar-foreground: var(--worktree-sidebar-foreground);
--color-worktree-sidebar-accent: var(--worktree-sidebar-accent);
--color-worktree-sidebar-accent-foreground: var(--worktree-sidebar-accent-foreground);
--color-worktree-sidebar-border: var(--worktree-sidebar-border);
--color-worktree-sidebar-ring: var(--worktree-sidebar-ring);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-accent: var(--sidebar-accent);
@ -137,6 +143,12 @@
--chart-3: var(--color-blue-600);
--chart-4: var(--color-blue-700);
--chart-5: var(--color-blue-800);
--worktree-sidebar: #f5f5f5;
--worktree-sidebar-foreground: #0a0a0a;
--worktree-sidebar-accent: #eaeaea;
--worktree-sidebar-accent-foreground: #171717;
--worktree-sidebar-border: #e5e5e5;
--worktree-sidebar-ring: #a1a1a1;
--sidebar: #fafafa;
--sidebar-foreground: #0a0a0a;
--sidebar-primary: #171717;
@ -210,6 +222,14 @@
--chart-3: var(--color-blue-600);
--chart-4: var(--color-blue-700);
--chart-5: var(--color-blue-800);
/* Why: light mode sets worktree-sidebar to secondary (#f5f5f5); mirror that
lift in dark mode so the panel reads clearly above #0a0a0a canvas. */
--worktree-sidebar: #2a2a2a;
--worktree-sidebar-foreground: #fafafa;
--worktree-sidebar-accent: #353535;
--worktree-sidebar-accent-foreground: #fafafa;
--worktree-sidebar-border: rgb(255 255 255 / 0.1);
--worktree-sidebar-ring: #737373;
--sidebar: #171717;
--sidebar-foreground: #fafafa;
--sidebar-primary: #1447e6;

View File

@ -85,10 +85,10 @@ function SettingsSetupGuideNavRow({
})
}
className={cn(
'flex w-full items-center gap-2 rounded-lg px-2.5 py-2 text-left outline-none transition-colors focus-visible:ring-[3px] focus-visible:ring-ring/50',
'flex w-full items-center gap-2 rounded-lg px-2.5 py-2 text-left outline-none transition-colors focus-visible:ring-[3px] focus-visible:ring-worktree-sidebar-ring/50',
setupActive
? 'bg-accent font-medium text-accent-foreground'
: 'text-muted-foreground hover:bg-muted/60 hover:text-foreground'
? 'bg-worktree-sidebar-accent font-medium text-worktree-sidebar-accent-foreground'
: 'text-worktree-sidebar-foreground/60 hover:bg-worktree-sidebar-foreground/8 hover:text-worktree-sidebar-foreground'
)}
>
<img
@ -130,10 +130,10 @@ export function SettingsSidebar({
const searchShortcutHint = useShortcutLabel('settings.search')
const navItemClassName = (isActive: boolean): string =>
cn(
'flex w-full items-center gap-2 rounded-lg px-3 py-1.5 text-left text-[13px] outline-none transition-colors focus-visible:ring-[3px] focus-visible:ring-ring/50',
'flex w-full items-center gap-2 rounded-lg px-3 py-1.5 text-left text-[13px] outline-none transition-colors focus-visible:ring-[3px] focus-visible:ring-worktree-sidebar-ring/50',
isActive
? 'bg-accent font-medium text-accent-foreground'
: 'text-muted-foreground hover:bg-muted/60 hover:text-foreground'
? 'bg-worktree-sidebar-accent font-medium text-worktree-sidebar-accent-foreground'
: 'text-worktree-sidebar-foreground/60 hover:bg-worktree-sidebar-foreground/8 hover:text-worktree-sidebar-foreground'
)
const installStatusLabel = (status: SettingsNavInstallStatus): string => {
switch (status) {
@ -156,8 +156,8 @@ export function SettingsSidebar({
)
return (
<aside className="flex w-[280px] shrink-0 flex-col border-r border-border/50 bg-card/40">
<div className="border-b border-border/50 px-3 py-3">
<aside className="flex w-[280px] shrink-0 flex-col border-r border-worktree-sidebar-border bg-worktree-sidebar">
<div className="border-b border-worktree-sidebar-border px-3 py-3">
<Button
variant="ghost"
size="sm"
@ -169,7 +169,7 @@ export function SettingsSidebar({
</Button>
</div>
<div className="border-b border-border/50 px-3 py-3">
<div className="border-b border-worktree-sidebar-border px-3 py-3">
<div className="relative">
<Search className="pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" />
<Input
@ -188,7 +188,7 @@ export function SettingsSidebar({
</div>
{showSetupGuideTopRow ? (
<div className="border-b border-border/50 px-3 py-3">
<div className="border-b border-worktree-sidebar-border px-3 py-3">
<SettingsSetupGuideNavRow
progress={setupGuideProgress}
setupActive={setupActive}

View File

@ -115,12 +115,12 @@ export default function ImportedWorktreesVisibilityLine({
return (
<section
aria-busy={pending}
className={cn('mx-1 my-0.5 ml-3 text-sidebar-foreground', className)}
className={cn('mx-1 my-0.5 ml-3 text-worktree-sidebar-foreground', className)}
>
<div
className={cn(
'flex min-h-7 min-w-0 items-center gap-1.5 rounded-md px-1.5 text-[11px] leading-none text-muted-foreground transition-colors',
'hover:bg-sidebar-accent hover:text-sidebar-accent-foreground'
'hover:bg-worktree-sidebar-accent hover:text-worktree-sidebar-accent-foreground'
)}
>
<Button
@ -131,7 +131,7 @@ export default function ImportedWorktreesVisibilityLine({
aria-expanded={isExpanded}
aria-label={`${isExpanded ? 'Collapse' : 'Expand'} hidden worktrees for ${repoDisplayName}`}
onClick={() => setIsExpanded((value) => !value)}
className="shrink-0 rounded-[4px] text-muted-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"
className="shrink-0 rounded-[4px] text-muted-foreground hover:bg-worktree-sidebar-accent hover:text-worktree-sidebar-accent-foreground"
>
<ChevronRight
className={cn('size-3 transition-transform', isExpanded && 'rotate-90')}
@ -150,7 +150,7 @@ export default function ImportedWorktreesVisibilityLine({
disabled={pending}
aria-label={keepHiddenAriaLabel}
onClick={onKeepHidden}
className="shrink-0 rounded-md text-muted-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground"
className="shrink-0 rounded-md text-muted-foreground hover:bg-worktree-sidebar-accent hover:text-worktree-sidebar-accent-foreground"
>
<X className="size-3" aria-hidden="true" />
</Button>
@ -164,7 +164,7 @@ export default function ImportedWorktreesVisibilityLine({
{isExpanded ? (
<div
className="ml-4 mt-0.5 grid gap-1 border-l border-sidebar-border pb-1 pl-2"
className="ml-4 mt-0.5 grid gap-1 border-l border-worktree-sidebar-border pb-1 pl-2"
aria-label="Hidden worktree groups"
>
{visibleWorktreeGroups.map((group) => (
@ -174,7 +174,7 @@ export default function ImportedWorktreesVisibilityLine({
<TooltipTrigger asChild>
<span
tabIndex={0}
className="block min-w-0 flex-1 truncate font-mono text-[10px] leading-4 text-muted-foreground outline-none focus-visible:ring-1 focus-visible:ring-sidebar-ring"
className="block min-w-0 flex-1 truncate font-mono text-[10px] leading-4 text-muted-foreground outline-none focus-visible:ring-1 focus-visible:ring-worktree-sidebar-ring"
>
{group.path}
</span>
@ -183,7 +183,7 @@ export default function ImportedWorktreesVisibilityLine({
{group.path}
</TooltipContent>
</Tooltip>
<span className="shrink-0 rounded-full border border-sidebar-border px-1.5 py-0.5 text-[10px] leading-none text-muted-foreground">
<span className="shrink-0 rounded-full border border-worktree-sidebar-border px-1.5 py-0.5 text-[10px] leading-none text-muted-foreground">
{group.worktrees.length}
</span>
</div>
@ -216,7 +216,7 @@ export default function ImportedWorktreesVisibilityLine({
size="xs"
disabled={pending}
onClick={() => toggleGroupExpanded(group.path)}
className="h-6 justify-start px-0 text-[11px] font-normal text-muted-foreground hover:text-sidebar-accent-foreground"
className="h-6 justify-start px-0 text-[11px] font-normal text-muted-foreground hover:text-worktree-sidebar-accent-foreground"
>
{expandedGroupPathKeys.has(normalizeRuntimePathForComparison(group.path))
? 'Show fewer'
@ -233,7 +233,7 @@ export default function ImportedWorktreesVisibilityLine({
</div>
) : null}
<div className="grid gap-1 px-1.5 pb-1 pt-1">
<p className="rounded-md bg-sidebar-accent px-2 py-1 text-[10px] font-medium leading-4 text-sidebar-accent-foreground">
<p className="rounded-md bg-worktree-sidebar-accent px-2 py-1 text-[10px] font-medium leading-4 text-worktree-sidebar-accent-foreground">
Change this later from the project menu.
</p>
<div className="flex min-w-0 items-center gap-1.5">

View File

@ -77,8 +77,8 @@ export function SetupGuideSidebarEntry(): React.JSX.Element | null {
className={cn(
'flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-[13px] font-medium tracking-tight transition-colors',
setupActive
? 'bg-sidebar-accent text-sidebar-accent-foreground'
: 'text-sidebar-foreground/60 hover:bg-sidebar-foreground/8'
? 'bg-worktree-sidebar-accent text-worktree-sidebar-accent-foreground'
: 'text-worktree-sidebar-foreground/60 hover:bg-worktree-sidebar-foreground/8'
)}
>
<img

View File

@ -381,7 +381,7 @@ function SetupScriptPromptCard(): React.JSX.Element | null {
return (
<div className="px-3 pb-2">
<div className="setup-script-prompt-card rounded-lg border border-sidebar-border p-3 text-sidebar-accent-foreground shadow-xs">
<div className="setup-script-prompt-card rounded-lg border border-worktree-sidebar-border p-3 text-worktree-sidebar-accent-foreground shadow-xs">
<div className="flex items-center justify-between gap-2">
<p className="text-sm font-semibold leading-snug">Add a setup script</p>
<DismissButton onDismiss={handleDismiss} />

View File

@ -44,7 +44,7 @@ export function DetectedSetupPreview({
provenance
}: DetectedSetupPreviewProps): React.JSX.Element {
return (
<div className="mt-3 border-t border-sidebar-border pt-3">
<div className="mt-3 border-t border-worktree-sidebar-border pt-3">
<div className="mb-2 flex items-center gap-1.5 text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">
<PackageCheck className="size-3.5" />
Detected setup
@ -55,7 +55,7 @@ export function DetectedSetupPreview({
onChange={(event) => onSetupChange(event.target.value)}
spellCheck={false}
rows={Math.min(Math.max(setup.split('\n').length, 2), 6)}
className="setup-script-prompt-command max-h-28 w-full resize-y overflow-auto scrollbar-sleek rounded-md border border-sidebar-border px-2 py-1.5 font-mono text-[11px] leading-5 text-foreground shadow-xs outline-none focus-visible:ring-1 focus-visible:ring-ring"
className="setup-script-prompt-command max-h-28 w-full resize-y overflow-auto scrollbar-sleek rounded-md border border-worktree-sidebar-border px-2 py-1.5 font-mono text-[11px] leading-5 text-foreground shadow-xs outline-none focus-visible:ring-1 focus-visible:ring-ring"
/>
{provenance ? (
<p className="mt-1.5 text-[11px] text-muted-foreground">

View File

@ -226,13 +226,16 @@ const SidebarNav = React.memo(function SidebarNav() {
className={cn(
'flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-[13px] font-medium tracking-tight transition-colors',
tasksActive
? 'bg-sidebar-accent text-sidebar-accent-foreground'
: 'text-sidebar-foreground/60 hover:bg-sidebar-foreground/8',
? 'bg-worktree-sidebar-accent text-worktree-sidebar-accent-foreground'
: 'text-worktree-sidebar-foreground/60 hover:bg-worktree-sidebar-foreground/8',
!canBrowseTasks && 'cursor-not-allowed opacity-50 hover:bg-transparent'
)}
>
<List
className={cn('size-4 shrink-0', !tasksActive && 'text-sidebar-foreground/30')}
className={cn(
'size-4 shrink-0',
!tasksActive && 'text-worktree-sidebar-foreground/30'
)}
strokeWidth={tasksActive ? 2.25 : 1.75}
/>
<span className="flex-1">Tasks</span>
@ -297,14 +300,14 @@ const SidebarNav = React.memo(function SidebarNav() {
className={cn(
'flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-[13px] font-medium tracking-tight transition-colors',
automationsActive
? 'bg-sidebar-accent text-sidebar-accent-foreground'
: 'text-sidebar-foreground/60 hover:bg-sidebar-foreground/8'
? 'bg-worktree-sidebar-accent text-worktree-sidebar-accent-foreground'
: 'text-worktree-sidebar-foreground/60 hover:bg-worktree-sidebar-foreground/8'
)}
>
<CalendarClock
className={cn(
'size-4 shrink-0',
!automationsActive && 'text-sidebar-foreground/30'
!automationsActive && 'text-worktree-sidebar-foreground/30'
)}
strokeWidth={automationsActive ? 2.25 : 1.75}
/>
@ -322,12 +325,15 @@ const SidebarNav = React.memo(function SidebarNav() {
className={cn(
'flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-[13px] font-medium tracking-tight transition-colors',
activityActive
? 'bg-sidebar-accent text-sidebar-accent-foreground'
: 'text-sidebar-foreground/60 hover:bg-sidebar-foreground/8'
? 'bg-worktree-sidebar-accent text-worktree-sidebar-accent-foreground'
: 'text-worktree-sidebar-foreground/60 hover:bg-worktree-sidebar-foreground/8'
)}
>
<Bell
className={cn('size-4 shrink-0', !activityActive && 'text-sidebar-foreground/30')}
className={cn(
'size-4 shrink-0',
!activityActive && 'text-worktree-sidebar-foreground/30'
)}
strokeWidth={activityActive ? 2.25 : 1.75}
/>
<span className="flex-1">Agents</span>
@ -351,12 +357,15 @@ const SidebarNav = React.memo(function SidebarNav() {
className={cn(
'flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-[13px] font-medium tracking-tight transition-colors',
mobileActive
? 'bg-sidebar-accent text-sidebar-accent-foreground'
: 'text-sidebar-foreground/60 hover:bg-sidebar-foreground/8'
? 'bg-worktree-sidebar-accent text-worktree-sidebar-accent-foreground'
: 'text-worktree-sidebar-foreground/60 hover:bg-worktree-sidebar-foreground/8'
)}
>
<Smartphone
className={cn('size-4 shrink-0', !mobileActive && 'text-sidebar-foreground/30')}
className={cn(
'size-4 shrink-0',
!mobileActive && 'text-worktree-sidebar-foreground/30'
)}
strokeWidth={mobileActive ? 2.25 : 1.75}
/>
<span className="flex-1">Orca Mobile</span>
@ -374,9 +383,12 @@ const SidebarNav = React.memo(function SidebarNav() {
type="button"
onClick={() => openModal('worktree-palette')}
aria-label="Search worktrees and browser tabs"
className="group flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-[13px] font-medium tracking-tight text-sidebar-foreground/60 transition-colors hover:bg-sidebar-foreground/8"
className="group flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-left text-[13px] font-medium tracking-tight text-worktree-sidebar-foreground/60 transition-colors hover:bg-worktree-sidebar-foreground/8"
>
<Search className="size-4 shrink-0 text-sidebar-foreground/30" strokeWidth={1.75} />
<Search
className="size-4 shrink-0 text-worktree-sidebar-foreground/30"
strokeWidth={1.75}
/>
<span className="flex-1">Search</span>
<kbd className="hidden rounded border border-border/60 bg-background/40 px-1.5 py-px font-mono text-[10px] font-medium text-muted-foreground group-hover:inline-flex items-center">
{worktreePaletteShortcut}

View File

@ -11,7 +11,7 @@ const SidebarToolbar = React.memo(function SidebarToolbar() {
return (
<div className="mt-auto shrink-0">
<div className="flex items-center justify-between border-t border-sidebar-border px-2 py-1.5">
<div className="flex items-center justify-between border-t border-worktree-sidebar-border px-2 py-1.5">
<Tooltip>
<TooltipTrigger asChild>
<Button

View File

@ -11,7 +11,7 @@ const WorkspaceKanbanAreaSelectionOverlay = React.forwardRef<
{...props}
ref={ref}
data-workspace-board-selection-rect=""
className="pointer-events-none absolute left-0 top-0 z-30 hidden rounded-md border border-sidebar-ring bg-sidebar-ring/15 will-change-transform"
className="pointer-events-none absolute left-0 top-0 z-30 hidden rounded-md border border-worktree-sidebar-ring bg-worktree-sidebar-ring/15 will-change-transform"
/>
)
})

View File

@ -35,7 +35,7 @@ function WorkspaceKanbanCard({
return (
<div
className="relative rounded-lg data-[workspace-board-card-area-selected=true]:ring-1 data-[workspace-board-card-area-selected=true]:ring-sidebar-ring/40"
className="relative rounded-lg data-[workspace-board-card-area-selected=true]:ring-1 data-[workspace-board-card-area-selected=true]:ring-worktree-sidebar-ring/40"
data-workspace-board-card-id={worktree.id}
data-workspace-board-card-mode="detailed"
data-workspace-board-card-selected={isSelected ? 'true' : 'false'}

View File

@ -477,7 +477,7 @@ export default function WorkspaceKanbanDrawer({
<SheetContent
side="left"
showCloseButton={false}
className="workspace-kanban-sheet-content bg-sidebar p-0 sm:max-w-none"
className="workspace-kanban-sheet-content bg-worktree-sidebar p-0 sm:max-w-none"
overlayStyle={{ top: 36, left: drawerLeftCss, pointerEvents: 'none' }}
style={
{

View File

@ -33,11 +33,11 @@ export default function WorkspaceKanbanDrawerHeader({
}: WorkspaceKanbanDrawerHeaderProps): React.JSX.Element {
return (
<>
<SheetHeader className="border-b border-sidebar-border px-4 py-3 pr-32">
<SheetHeader className="border-b border-worktree-sidebar-border px-4 py-3 pr-32">
<SheetTitle className="flex items-center gap-2 text-sm">
<span>Workspace board</span>
{selectedCount > 1 ? (
<span className="rounded-full bg-sidebar-accent px-2 py-0.5 text-[10px] font-medium text-muted-foreground">
<span className="rounded-full bg-worktree-sidebar-accent px-2 py-0.5 text-[10px] font-medium text-muted-foreground">
{selectedCount} selected
</span>
) : null}

View File

@ -17,9 +17,9 @@ export default function WorkspaceKanbanPinDropTarget({
<div
data-workspace-pin-drop-target=""
className={cn(
'mb-3 flex h-8 shrink-0 items-center gap-2 rounded-md border border-dashed border-sidebar-border bg-background/45 px-3 text-[12px] text-muted-foreground transition-colors',
isDragOver && 'border-sidebar-ring bg-sidebar-accent text-foreground',
'data-[workspace-board-external-drag-target=true]:border-sidebar-ring data-[workspace-board-external-drag-target=true]:bg-sidebar-accent data-[workspace-board-external-drag-target=true]:text-foreground'
'mb-3 flex h-8 shrink-0 items-center gap-2 rounded-md border border-dashed border-worktree-sidebar-border bg-background/45 px-3 text-[12px] text-muted-foreground transition-colors',
isDragOver && 'border-worktree-sidebar-ring bg-worktree-sidebar-accent text-foreground',
'data-[workspace-board-external-drag-target=true]:border-worktree-sidebar-ring data-[workspace-board-external-drag-target=true]:bg-worktree-sidebar-accent data-[workspace-board-external-drag-target=true]:text-foreground'
)}
onDragOver={onDragOver}
onDragLeave={onDragLeave}

View File

@ -86,11 +86,11 @@ export default function WorkspaceKanbanStatusLane({
}
className={cn(
'group/lane',
'relative flex h-full min-h-0 min-w-0 flex-col overflow-hidden rounded-md border border-t-2 border-sidebar-border transition-colors',
'relative flex h-full min-h-0 min-w-0 flex-col overflow-hidden rounded-md border border-t-2 border-worktree-sidebar-border transition-colors',
meta.border,
meta.laneTint,
isDragTarget && 'border-sidebar-ring bg-sidebar-accent/70',
'data-[workspace-board-external-drag-target=true]:border-sidebar-ring data-[workspace-board-external-drag-target=true]:bg-sidebar-accent/70'
isDragTarget && 'border-worktree-sidebar-ring bg-worktree-sidebar-accent/70',
'data-[workspace-board-external-drag-target=true]:border-worktree-sidebar-ring data-[workspace-board-external-drag-target=true]:bg-worktree-sidebar-accent/70'
)}
onDragOver={(event) => onDragOver(event, status.id)}
onDragLeave={onDragLeave}
@ -107,7 +107,7 @@ export default function WorkspaceKanbanStatusLane({
tabIndex={0}
className={cn(
'group absolute right-0 top-0 z-20 h-9 w-2 cursor-col-resize outline-none',
'focus-visible:ring-1 focus-visible:ring-sidebar-ring',
'focus-visible:ring-1 focus-visible:ring-worktree-sidebar-ring',
isResizingColumn && 'cursor-col-resize'
)}
onPointerDown={onColumnResizeStart}
@ -117,8 +117,8 @@ export default function WorkspaceKanbanStatusLane({
<span
className={cn(
'absolute inset-y-2 left-1/2 w-px -translate-x-1/2 rounded-full bg-transparent transition-colors',
'group-hover:bg-sidebar-ring/55 group-focus-visible:bg-sidebar-ring',
isResizingColumn && 'bg-sidebar-ring'
'group-hover:bg-worktree-sidebar-ring/55 group-focus-visible:bg-worktree-sidebar-ring',
isResizingColumn && 'bg-worktree-sidebar-ring'
)}
/>
</div>

View File

@ -116,7 +116,7 @@ function RepoIdentityChip({
<Tooltip>
<TooltipTrigger asChild>
<span
className="inline-flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-sidebar-border bg-sidebar-accent/55"
className="inline-flex size-4 shrink-0 items-center justify-center rounded-[4px] border border-worktree-sidebar-border bg-worktree-sidebar-accent/55"
aria-label={`Project ${repo.displayName}`}
>
{children}
@ -761,9 +761,9 @@ const WorktreeCard = React.memo(function WorktreeCard({
isActiveSurface
? 'bg-black/[0.08] shadow-[0_1px_2px_rgba(0,0,0,0.04)] border border-black/[0.015] dark:bg-white/[0.10] dark:border-border/40 dark:shadow-[0_1px_2px_rgba(0,0,0,0.03)]'
: isMultiSelected
? 'border border-sidebar-ring/35 bg-sidebar-accent/70 ring-1 ring-sidebar-ring/30'
? 'border border-worktree-sidebar-ring/35 bg-worktree-sidebar-accent/70 ring-1 ring-worktree-sidebar-ring/30'
: 'border border-transparent worktree-sidebar-card-hover',
isActiveSurface && isMultiSelected && 'ring-1 ring-sidebar-ring/35',
isActiveSurface && isMultiSelected && 'ring-1 ring-worktree-sidebar-ring/35',
revealHighlight && [
'scroll-to-current-workspace-reveal-highlight',
revealHighlightTone === 'ai' && 'scroll-to-current-workspace-reveal-highlight--ai'
@ -876,7 +876,7 @@ const WorktreeCard = React.memo(function WorktreeCard({
onPointerDown={stopQuickActionPointerPropagation}
onClick={handlePendingFirstAgentMessageRenameInfo}
onDoubleClick={handlePendingFirstAgentMessageRenameInfo}
className="h-4 shrink-0 gap-0.5 rounded !px-0.5 text-[10px] font-medium leading-none text-muted-foreground border border-sidebar-border/60 bg-sidebar-accent/45 hover:bg-sidebar-accent hover:text-foreground has-[>svg]:!px-0.5"
className="h-4 shrink-0 gap-0.5 rounded !px-0.5 text-[10px] font-medium leading-none text-muted-foreground border border-worktree-sidebar-border/60 bg-worktree-sidebar-accent/45 hover:bg-worktree-sidebar-accent hover:text-foreground has-[>svg]:!px-0.5"
aria-label="Will be renamed from first agent message"
>
<Sparkles className="size-2.5" />
@ -1067,7 +1067,9 @@ const WorktreeCard = React.memo(function WorktreeCard({
{showLineageChildChip && (
<div
className="relative mt-1 flex min-w-0 justify-start"
style={{ color: 'color-mix(in srgb, var(--muted-foreground) 42%, var(--sidebar))' }}
style={{
color: 'color-mix(in srgb, var(--muted-foreground) 42%, var(--worktree-sidebar))'
}}
>
<Tooltip>
<TooltipTrigger asChild>
@ -1075,7 +1077,7 @@ const WorktreeCard = React.memo(function WorktreeCard({
type="button"
variant="ghost"
size="xs"
className="relative z-10 h-[18px] max-w-[8rem] gap-1 rounded-md border border-sidebar-border bg-sidebar px-1.5 text-[10px] font-medium leading-none text-muted-foreground shadow-none hover:bg-sidebar-accent hover:text-foreground focus-visible:ring-1 focus-visible:ring-sidebar-ring"
className="relative z-10 h-[18px] max-w-[8rem] gap-1 rounded-md border border-worktree-sidebar-border bg-worktree-sidebar px-1.5 text-[10px] font-medium leading-none text-muted-foreground shadow-none hover:bg-worktree-sidebar-accent hover:text-foreground focus-visible:ring-1 focus-visible:ring-worktree-sidebar-ring"
aria-label={`${lineageCollapsed ? 'Show' : 'Hide'} ${childWorkspaceLabel}`}
aria-expanded={!lineageCollapsed}
onClick={onLineageToggle}

View File

@ -39,7 +39,7 @@ export function WorktreeCardPortsTrigger({
return (
<button
type="button"
className="inline-flex size-3.5 shrink-0 items-center justify-center rounded text-muted-foreground/70 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-sidebar-ring"
className="inline-flex size-3.5 shrink-0 items-center justify-center rounded text-muted-foreground/70 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-worktree-sidebar-ring"
aria-label={`${ports.length} live ${ports.length === 1 ? 'port' : 'ports'}`}
onClick={(event) => {
event.stopPropagation()

View File

@ -444,7 +444,7 @@ function SectionMetricsBadge({ count }: { count: number }): React.JSX.Element {
return (
<span
className="inline-flex h-4 shrink-0 overflow-hidden rounded-full border border-sidebar-border bg-sidebar-accent text-[9px] font-medium leading-none text-muted-foreground/90"
className="inline-flex h-4 shrink-0 overflow-hidden rounded-full border border-worktree-sidebar-border bg-worktree-sidebar-accent text-[9px] font-medium leading-none text-muted-foreground/90"
aria-label={totalLabel}
>
<Tooltip>
@ -2776,9 +2776,9 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
className="pointer-events-none absolute left-3 right-2 z-30 flex h-3 -translate-y-1/2 items-center"
style={{ top: `${worktreeDragState.dropIndicatorY}px` }}
>
<span className="size-1.5 shrink-0 rounded-full bg-sidebar-ring shadow-[0_0_0_2px_var(--sidebar)]" />
<span className="h-0.5 flex-1 rounded-full bg-sidebar-ring shadow-[0_0_0_2px_var(--sidebar)]" />
<span className="size-1.5 shrink-0 rounded-full bg-sidebar-ring shadow-[0_0_0_2px_var(--sidebar)]" />
<span className="size-1.5 shrink-0 rounded-full bg-worktree-sidebar-ring shadow-[0_0_0_2px_var(--worktree-sidebar)]" />
<span className="h-0.5 flex-1 rounded-full bg-worktree-sidebar-ring shadow-[0_0_0_2px_var(--worktree-sidebar)]" />
<span className="size-1.5 shrink-0 rounded-full bg-worktree-sidebar-ring shadow-[0_0_0_2px_var(--worktree-sidebar)]" />
</div>
) : null}
{virtualItems.map((vItem) => {
@ -2846,7 +2846,9 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
// reaches the top (see getActiveStickyHeaderIndexForScroll),
// so the previous repo no longer stays pinned over it.
hasHeaderTopSpacing && !isActiveStickyHeader && 'pt-1',
isActiveStickyHeader ? 'sticky -top-px z-20 bg-sidebar' : 'absolute top-0'
isActiveStickyHeader
? 'sticky -top-px z-20 bg-worktree-sidebar'
: 'absolute top-0'
)}
style={
isActiveStickyHeader
@ -2868,10 +2870,10 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
'bg-accent/80 ring-1 ring-ring/40 shadow-md rounded-md scale-[1.01]',
headerWorkspaceStatus &&
dragOverStatus === headerWorkspaceStatus &&
'rounded-md bg-sidebar-accent ring-1 ring-sidebar-ring/40',
'rounded-md bg-worktree-sidebar-accent ring-1 ring-worktree-sidebar-ring/40',
isPinnedHeader &&
pinDragOver &&
'rounded-md bg-sidebar-accent ring-1 ring-sidebar-ring/40',
'rounded-md bg-worktree-sidebar-accent ring-1 ring-worktree-sidebar-ring/40',
row.repo && 'overflow-hidden'
)}
style={{ paddingLeft: headerPaddingLeft }}
@ -3426,7 +3428,7 @@ const VirtualizedWorktreeViewport = React.memo(function VirtualizedWorktreeViewp
type="button"
variant="ghost"
size="xs"
className="h-[18px] max-w-[8rem] gap-1 rounded-md border border-sidebar-border bg-sidebar px-1.5 text-[10px] font-medium leading-none text-muted-foreground shadow-none hover:bg-sidebar-accent hover:text-foreground focus-visible:ring-1 focus-visible:ring-sidebar-ring"
className="h-[18px] max-w-[8rem] gap-1 rounded-md border border-worktree-sidebar-border bg-worktree-sidebar px-1.5 text-[10px] font-medium leading-none text-muted-foreground shadow-none hover:bg-worktree-sidebar-accent hover:text-foreground focus-visible:ring-1 focus-visible:ring-worktree-sidebar-ring"
aria-label={`${child.lineageCollapsed ? 'Show' : 'Hide'} ${
child.lineageChildCount
} child ${

View File

@ -263,7 +263,7 @@ export function WorktreeTitleInlineRename({
key={`title:${titleElementKey}`}
ref={handleRootRef}
className={cn(
'block min-w-0 truncate leading-tight text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-sidebar-ring',
'block min-w-0 truncate leading-tight text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-worktree-sidebar-ring',
showUnreadEmphasis ? 'font-semibold' : 'font-normal',
className
)}

View File

@ -69,7 +69,7 @@ function Sidebar({
<div
ref={containerRef}
data-native-file-drop-target={sidebarOpen ? nativeDropTarget : undefined}
className="relative min-h-0 flex-shrink-0 bg-sidebar flex flex-col overflow-hidden scrollbar-sleek-parent"
className="relative min-h-0 flex-shrink-0 bg-worktree-sidebar flex flex-col overflow-hidden scrollbar-sleek-parent"
{...dropHandlers}
>
{sidebarOpen && (
@ -93,8 +93,10 @@ function Sidebar({
{sidebarOpen && affordance.visible ? (
<div
className={cn(
'pointer-events-none absolute inset-2 z-20 flex flex-col items-center justify-center gap-1.5 rounded-md border bg-sidebar-accent/95 px-4 text-center text-sidebar-accent-foreground shadow-xs',
affordance.tone === 'blocked' ? 'border-destructive/70' : 'border-sidebar-ring/70'
'pointer-events-none absolute inset-2 z-20 flex flex-col items-center justify-center gap-1.5 rounded-md border bg-worktree-sidebar-accent/95 px-4 text-center text-worktree-sidebar-accent-foreground shadow-xs',
affordance.tone === 'blocked'
? 'border-destructive/70'
: 'border-worktree-sidebar-ring/70'
)}
>
{affordance.tone === 'busy' ? (

View File

@ -166,15 +166,15 @@ export function CompactAgentSummaryButton({
className={cn(
'compact-agent-summary-button group/agent-summary flex h-6 w-full min-w-0 items-center gap-1 rounded-sm',
'px-1 text-left text-[11px] leading-none text-muted-foreground',
'focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-sidebar-ring',
// Why: sidebar-accent is near-white in light mode and dark in dark
'focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-worktree-sidebar-ring',
// Why: worktree-sidebar-accent is near-white in light mode and dark in dark
// mode, so hover lightening needs a theme-specific token mix.
'hover:bg-sidebar-accent/55 dark:hover:bg-sidebar-foreground/[0.035]',
'hover:bg-worktree-sidebar-accent/55 dark:hover:bg-worktree-sidebar-foreground/[0.035]',
// Why: expanded is a tree header inside the card, so only the
// standalone collapsed pill gets a resting surface and border.
expanded
? 'compact-agent-summary-button-expanded'
: 'border border-sidebar-border/70 bg-sidebar-accent/35'
: 'border border-worktree-sidebar-border/70 bg-worktree-sidebar-accent/35'
)}
aria-label={
expanded ? `Collapse ${subjectLabel}` : `Expand ${summary}. ${agentIdentitySummary}`
@ -199,7 +199,7 @@ export function CompactAgentSummaryButton({
return (
<span
key={group.state}
className="inline-flex min-w-0 shrink-0 items-center gap-0.5 rounded-sm bg-sidebar/70 px-1 py-0.5"
className="inline-flex min-w-0 shrink-0 items-center gap-0.5 rounded-sm bg-worktree-sidebar/70 px-1 py-0.5"
>
<AgentStateDot state={group.state} size="sm" />
{/* Why: same-state agent identities read as one status cluster;
@ -208,7 +208,7 @@ export function CompactAgentSummaryButton({
{iconAgents.map((agent) => (
<span
key={agent.paneKey}
className="inline-flex size-4 items-center justify-center rounded-full border border-sidebar-border/70 bg-sidebar"
className="inline-flex size-4 items-center justify-center rounded-full border border-worktree-sidebar-border/70 bg-worktree-sidebar"
>
<AgentIcon agent={agentTypeToIconAgent(agent.agentType)} size={13} />
</span>
@ -296,7 +296,7 @@ export const CompactAgentRow = React.memo(function CompactAgentRow({
{hasChildDisclosure ? (
<button
type="button"
className="compact-agent-child-disclosure-button flex size-4 shrink-0 items-center justify-center rounded-sm text-muted-foreground hover:bg-sidebar-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-sidebar-ring"
className="compact-agent-child-disclosure-button flex size-4 shrink-0 items-center justify-center rounded-sm text-muted-foreground hover:bg-worktree-sidebar-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-worktree-sidebar-ring"
aria-label={`${childAgentsExpanded ? 'Hide' : 'Show'} ${childAgentCount} child ${
childAgentCount === 1 ? 'agent' : 'agents'
}`}
@ -365,7 +365,7 @@ export const CompactAgentRow = React.memo(function CompactAgentRow({
hasChildDisclosure && 'worktree-agent-lineage-parent-row',
isLineageChild && 'worktree-agent-lineage-child-row',
hasAssistantImage ? 'flex flex-col py-0.5' : 'flex h-6 items-center gap-1',
isFocusedPane && 'bg-sidebar-accent'
isFocusedPane && 'bg-worktree-sidebar-accent'
)}
onClick={handleActivate}
onMouseDown={(e) => e.stopPropagation()}