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:
parent
76cb846d68
commit
1826609215
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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} />
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
/>
|
||||
)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -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'}
|
||||
|
|
|
|||
|
|
@ -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={
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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 ${
|
||||
|
|
|
|||
|
|
@ -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
|
||||
)}
|
||||
|
|
|
|||
|
|
@ -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' ? (
|
||||
|
|
|
|||
|
|
@ -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()}
|
||||
|
|
|
|||
Loading…
Reference in New Issue