Files
orca/DESIGN.md
T
Neil a9cef50687 docs: add DESIGN.md describing Orca's visual identity (#981)
Adds a DESIGN.md following the google-labs-code/design.md alpha spec so
agents and contributors have a single structured source of truth for
Orca's tokens (colors, typography, rounded, spacing, components) and the
prose rationale for when and how to apply them.

Tokens are derived from src/renderer/src/assets/main.css and the Button
CVA in src/renderer/src/components/ui/button.tsx, with a parallel
dark-colors block for the .dark theme remap. Tightens muted-foreground
(#737373 -> #6B6B6B) and ring (#a1a1a1 -> #8E8E8E) to the WCAG AA /
non-text 3:1 thresholds; an a11y note flags these as the normative
target for the CSS variables.

Passes the official `npx @google/design.md lint` with 0 errors.
2026-05-14 02:05:06 -07:00

24 KiB
Raw Blame History

version, name, description, colors, dark-colors, typography, rounded, spacing, components
version name description colors dark-colors typography rounded spacing components
alpha Orca Visual identity for Orca, a desktop AI-orchestration IDE for running Claude Code, Codex, and other CLI agents side-by-side across git worktrees. Tokens describe the default (light) theme; a parallel dark theme is documented in prose.
background foreground card card-foreground popover popover-foreground primary primary-foreground secondary secondary-foreground muted muted-foreground accent accent-foreground destructive destructive-foreground border input ring sidebar sidebar-foreground sidebar-primary sidebar-primary-foreground sidebar-accent sidebar-accent-foreground sidebar-border sidebar-ring editor-surface git-added git-modified git-deleted git-renamed git-untracked agent-active
#ffffff #0a0a0a #ffffff #0a0a0a #ffffff #0a0a0a #171717 #fafafa #f5f5f5 #171717 #f5f5f5 #6B6B6B #f5f5f5 #171717 #e40014 #fcf3f3 #e5e5e5 #e5e5e5 #8E8E8E #fafafa #0a0a0a #171717 #fafafa #f5f5f5 #171717 #e5e5e5 #a1a1a1 #ffffff #587c0c #895503 #ad0707 #007acc #007100 #16a34a
background foreground card card-foreground popover popover-foreground primary primary-foreground secondary secondary-foreground muted muted-foreground accent accent-foreground destructive destructive-foreground border input ring sidebar sidebar-foreground sidebar-primary sidebar-primary-foreground sidebar-accent sidebar-accent-foreground sidebar-border sidebar-ring editor-surface git-added git-modified git-deleted git-renamed git-untracked agent-active
#0a0a0a #fafafa #171717 #fafafa #171717 #fafafa #e5e5e5 #171717 #262626 #fafafa #262626 #a1a1a1 #404040 #fafafa #ff6568 #df2225 rgba(255, 255, 255, 0.07) rgba(255, 255, 255, 0.15) #737373 #171717 #fafafa #1447e6 #fafafa #262626 #fafafa rgba(255, 255, 255, 0.07) #525252 #1e1e1e #81b88b #e2c08d #c74e39 #73c991 #73c991 #16a34a
display headline-lg headline-md body-md body-sm label-lg label-md label-sm label-caps mono-sm
fontFamily fontSize fontWeight lineHeight letterSpacing
Geist, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif 48px 700 1.1 -0.02em
fontFamily fontSize fontWeight lineHeight letterSpacing
Geist, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif 18px 600 1.2 0.01em
fontFamily fontSize fontWeight lineHeight letterSpacing
Geist, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif 14px 600 1.3 0.01em
fontFamily fontSize fontWeight lineHeight letterSpacing
Geist, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif 14px 400 1.5 0.01em
fontFamily fontSize fontWeight lineHeight letterSpacing
Geist, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif 13px 400 1.45 0.01em
fontFamily fontSize fontWeight lineHeight letterSpacing
Geist, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif 14px 500 1.2 0.01em
fontFamily fontSize fontWeight lineHeight letterSpacing
Geist, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif 12px 500 1.2 0.01em
fontFamily fontSize fontWeight lineHeight letterSpacing
Geist, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif 11px 500 1.2 0.01em
fontFamily fontSize fontWeight lineHeight letterSpacing
Geist, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif 11px 600 1.2 0.05em
fontFamily fontSize fontWeight lineHeight
'SF Mono', SFMono-Regular, ui-monospace, 'Cascadia Code', Menlo, Consolas, 'Liberation Mono', monospace 12px 400 1.45
none sm md lg xl 2xl full
0px 6px 8px 10px 14px 18px 9999px
base xs sm md lg xl 2xl titlebar-height sidebar-width-default sidebar-width-min sidebar-width-max traffic-light-pad
4px 4px 8px 12px 16px 24px 32px 42px 280px 220px 500px 80px
titlebar sidebar sidebar-item sidebar-item-active button-primary button-primary-hover button-secondary button-secondary-hover button-outline button-outline-hover button-ghost button-ghost-hover button-destructive button-destructive-hover button-sm button-lg button-xs icon-button icon-button-hover input card badge agent-badge
backgroundColor textColor height
{colors.card} {colors.foreground} {spacing.titlebar-height}
backgroundColor textColor width
{colors.sidebar} {colors.sidebar-foreground} {spacing.sidebar-width-default}
backgroundColor textColor rounded padding typography
transparent {colors.sidebar-foreground} {rounded.sm} 8px 12px {typography.body-sm}
backgroundColor textColor
{colors.sidebar-accent} {colors.sidebar-accent-foreground}
backgroundColor textColor typography rounded height padding
{colors.primary} {colors.primary-foreground} {typography.label-lg} {rounded.md} 36px 0 16px
backgroundColor
{colors.primary}
backgroundColor textColor typography rounded height padding
{colors.secondary} {colors.secondary-foreground} {typography.label-lg} {rounded.md} 36px 0 16px
backgroundColor textColor
{colors.secondary} {colors.secondary-foreground}
backgroundColor textColor borderColor typography rounded height padding
{colors.background} {colors.foreground} {colors.border} {typography.label-lg} {rounded.md} 36px 0 16px
backgroundColor textColor borderColor
{colors.accent} {colors.accent-foreground} {colors.border}
backgroundColor textColor typography rounded height padding
transparent {colors.foreground} {typography.label-lg} {rounded.md} 36px 0 16px
backgroundColor textColor
{colors.accent} {colors.accent-foreground}
backgroundColor textColor typography rounded height padding
{colors.destructive} #ffffff {typography.label-lg} {rounded.md} 36px 0 16px
backgroundColor textColor
{colors.destructive} #ffffff
typography rounded height padding
{typography.label-lg} {rounded.sm} 32px 0 12px
typography rounded height padding
{typography.label-lg} {rounded.sm} 40px 0 24px
typography rounded height padding
{typography.label-md} {rounded.sm} 24px 0 8px
backgroundColor textColor rounded size
transparent {colors.muted-foreground} {rounded.sm} 36px
backgroundColor textColor
{colors.accent} {colors.foreground}
backgroundColor textColor borderColor typography rounded height padding
{colors.background} {colors.foreground} {colors.input} {typography.body-sm} {rounded.md} 36px 0 12px
backgroundColor textColor borderColor rounded padding
{colors.card} {colors.card-foreground} {colors.border} {rounded.lg} 16px
backgroundColor textColor typography rounded padding
{colors.accent} {colors.accent-foreground} {typography.label-sm} {rounded.full} 2px 8px
backgroundColor textColor typography rounded padding
{colors.accent} {colors.foreground} {typography.label-sm} {rounded.full} 3px 8px

Orca Design System

Overview

Orca is a desktop IDE for developers who run multiple AI coding agents in parallel. The product surface is dense with signal — worktrees, agents, terminals, diffs, PR state — and the visual language has to stay out of the way so that signal reads cleanly.

The personality is quiet, precise, and native. Orca should feel like it belongs next to a terminal and a code editor, not a marketing site. Surfaces are flat, chrome is thin, color is reserved for state that actually matters (agent activity, git status, destructive actions). Motion is short and functional.

Orca supports both light and dark themes from a single semantic token set. The tokens in this file describe the default (light) theme; the dark theme remaps the same semantic names — see Colors → Dark mode.

Colors

The palette is built on two layered neutrals plus a single strong destructive red. Everything else — backgrounds, borders, text — is a shade of gray chosen to preserve a clear type hierarchy at small sizes in dense UIs.

  • Primary (#171717): Near-black ink. Used for the default Button, for active sidebar states in dark mode, and as foreground on primary surfaces. Not a "brand" color in the marketing sense — it's the highest- contrast ink available against the neutral canvas.
  • Foreground / Background: #0a0a0a on #ffffff (light) and #fafafa on #0a0a0a (dark). The text-on-background pair is intentionally a few points off pure black/white to reduce eye strain during long coding sessions.
  • Muted Foreground (#6B6B6B): The workhorse for captions, metadata, timestamps, worktree paths, inactive icon buttons, and any text that should recede. Roughly 60% of text in a typical Orca screen uses this.
  • Secondary / Muted / Accent (#f5f5f5): A single off-white fill shared across hover states, badges, pills, and the sidebar's active item. Orca intentionally collapses several shadcn roles onto the same value so that hover, selection, and filled chips all share one visual layer — this keeps the surface quiet.
  • Border (#e5e5e5): One hairline color for nearly every divider. Dividers in Orca are never stronger than the type they separate.
  • Destructive (#e40014): Reserved for delete actions, error states, and destructive confirmations. Never used decoratively.
  • Ring (#8E8E8E): Focus outline. Always visible via keyboard, never suppressed.

A11y note: muted-foreground (#6B6B6B) and ring (#8E8E8E) are one step darker than the values currently committed in src/renderer/src/assets/main.css (#737373 / #a1a1a1), which sit just below WCAG thresholds (4.35:1 for body text on muted, 2.58:1 for focus-ring non-text contrast on background). This file is the normative target; the CSS variables should be aligned to these values.

Git decoration

Orca ships its own source-control view and keeps a dedicated set of status colors that are distinct from product semantic colors. These are tuned against the VS Code convention so they feel familiar to users coming from an editor.

  • git-added #587c0c (light) / #81b88b (dark)
  • git-modified #895503 (light) / #e2c08d (dark)
  • git-deleted #ad0707 (light) / #c74e39 (dark)
  • git-renamed #007acc (light) / #73c991 (dark)
  • git-untracked #007100 (light) / #73c991 (dark)

Agent activity

A dedicated green #16a34a signals a running agent and is applied as a small solid dot with an 18%-alpha halo inside the titlebar agent badge and hover cards. Idle agents use muted-foreground — green always means "something is actively happening right now."

Reserved role: sidebar-primary

The sidebar-primary token is defined (#171717 light / #1447e6 dark) as a reserved role for a future active-workspace indicator. It is not currently consumed by any component — the active sidebar state today uses sidebar-accent. Treat sidebar-primary as a held slot, not a rule to apply.

Dark mode

The dark theme remaps the same semantic names. Key differences:

  • background: #0a0a0a, foreground: #fafafa
  • editor-surface: #1e1e1e — a dedicated dark gray for embedded Monaco editor panes so they match the host editor feel instead of the full app background.
  • primary: #e5e5e5 with primary-foreground: #171717 — button inks invert cleanly.
  • Borders become rgba(255, 255, 255, 0.07) — barely-visible 1px lines that separate panes without adding weight.
  • destructive: #ff6568 — shifted lighter for AA contrast on dark.

Typography

Orca uses Geist (variable, weights 100900) as the single product typeface, with -apple-system / Segoe UI as cross-platform fallbacks and SF Mono / ui-monospace for code, file paths, and terminal UI.

Geist was chosen because it renders well at 1114px — the range where ~90% of Orca's type lives — and because its metrics hold up next to Monaco editor content without creating visible baseline jumps.

The system is tuned for small sizes. There is no full marketing type scale; Orca runs in a window, not on a landing page.

  • Display (48px / 700): Reserved for the Landing empty-state and nothing else. Uses muted-foreground deliberately — the landing title is a wayfinding cue, not a headline.
  • Headline lg/md (18/14, 600): Section titles inside dialogs and editor panes. Never stacked; Orca does not have multi-level headline hierarchy inside a view.
  • Body (14/13, 400): Default reading size. 14px for primary text and editor chrome, 13px for list items and sidebar entries.
  • Label (12/11, 500): Buttons, badges, input affordances, dropdowns. Buttons always use label sizing — never body — so they read as interactive at a glance.
  • Label caps (11px, 600, tracking 0.05em): Used for small section headers in the sidebar and metadata rows ("WORKTREES", "OPENED FILES").
  • Mono (12px): Worktree paths, commit SHAs, branch names, terminal UI, and the editor-header path row.

All weights set a global letter-spacing: 0.01em via body to compensate for Geist's slightly tight default tracking at small sizes. Display-size text uses negative tracking (-0.02em) for optical balance.

Layout

Orca is a single fixed window laid out as a column stack: a 42px titlebar, then a flexible content row containing the sidebar and the main work area. Nothing scrolls the whole window — only individual panes scroll.

  • Titlebar (42px): Acts as both the macOS drag region and the global status strip. Contains the sidebar toggle, the agent-activity badge, and window-level icon buttons. On macOS, an 80px traffic-light pad reserves space for the native window controls.
  • Sidebar (default 280px, user-resizable between 220px and 500px, and collapsible to 0): Holds a fixed-top nav row, a header, a search bar, the virtualized worktree list, and a fixed-bottom toolbar. A 4px-wide drag hitbox on the sidebar's right edge drives the resize (absolute- positioned, transparent until hovered, then tinted with ring/20). The hitbox is the interactive surface — there is no separate visible 1px divider; the sidebar's own sidebar-border supplies the hairline. The persisted width is clamped into the min/max range on load. Collapsed state removes the right border entirely so the content area extends edge-to-edge.
  • Content area: Horizontal flex, 100% width minus sidebar. Worktree views may subdivide further into editor / terminal / right-sidebar columns using resizable dividers.

Spacing scale

Orca uses a 4px base grid with semantic increments. Most surface padding lands at 8px (tight list rows), 12px (sidebar items, input insets), or 16px (card padding, dialog bodies). 24px and above are reserved for modals and landing content. Avoid 2px, 6px, 10px — off-grid values create visible rhythm breaks when panes sit side by side.

  • xs: 4px — icon-to-label gaps, pill padding
  • sm: 8px — compact list rows, badge padding
  • md: 12px — sidebar item padding, input horizontal padding
  • lg: 16px — card interior, dialog body
  • xl: 24px — modal padding, landing gaps
  • 2xl: 32px — landing vertical rhythm

Elevation & Depth

Orca is a flat, layered interface. There is no Material-style elevation model. Hierarchy is conveyed by:

  1. Tonal surfaces. sidebar (#fafafa) sits on background (#ffffff) in light; in dark, editor-surface (#1e1e1e) sits on background (#0a0a0a). These tonal steps do the work of shadow.
  2. Hairline borders. A single border value (#e5e5e5 light / rgba(255,255,255,0.07) dark) separates panes. Borders are never doubled and never combined with shadow on the same edge.
  3. Focused shadows, sparingly. Popovers, dropdowns, and dialogs use a subtle drop shadow (approx. 0 1px 2px rgba(0,0,0,0.05) light, stronger on dark). Diff-comment popovers, which overlay the editor, use a heavier 0 10px 24px rgba(0,0,0,0.18) because they must clearly separate from busy code underneath.
  4. Colored rings for focus. Keyboard focus uses a 3px ring at ring/50 alpha plus a border recolor. Focus is a depth cue, not a color accent.

Flash/pulse animations (e.g. settings-section-flash on anchor-scroll) are 300900ms eased fades applied to the ring color — they announce a destination without persisting chrome.

Shapes

Orca uses soft-rectangular geometry. The base radius is --radius: 0.625rem (10px); the Tailwind scale derives from it as 0.6×/0.8×/1×/1.4×/1.8×.

  • Buttons, inputs, list rows: rounded-md (8px). The default UI radius — large enough to read as modern, small enough to sit cleanly against square editor content.
  • Cards, dialogs: rounded-lg (10px) to rounded-xl (14px).
  • Badges, pills, dots, agent indicators: rounded-full (9999px).
  • Sharp corners (0px): Scrollbar thumbs, Monaco find-widget internals, and the worktree-pane dividers. Anything that sits flush against the window edge or inside a tool surface stays square.

Do not mix sm and lg radii on the same object. A card with a rounded-xl outer edge should not contain a button with rounded-sm corners — the eye reads the mismatch as a layout bug.

Components

Buttons

Buttons are built with class-variance-authority; six variants × four sizes. See src/renderer/src/components/ui/button.tsx.

Variants:

  • default — primary ink fill, used for the single most important action in a dialog or form. At most one per screen region.
  • secondary — soft-gray fill. Non-committal affirmative action.
  • outline — 1px border + background. Dismissive / cancel actions when paired with a default primary.
  • ghost — no chrome until hover. The most common button in Orca, used for icon buttons, sidebar actions, and title-bar controls.
  • destructive — red fill. Used for confirmation buttons in a destructive dialog, never in the main UI.
  • link — unadorned primary-colored text with underline-on-hover. For in-flow navigation, not as a CTA.

Sizes: xs (24px), sm (32px), default (36px), lg (40px), plus matching icon-only sizes. Default icon buttons share button height with text buttons so toolbars align.

Default/sm/lg buttons use label-lg typography (14px / 500); only the xs size drops to label-md (12px / 500). Buttons never use body weight (400) so that interactivity reads at a glance even without chrome (ghost variant).

Titlebar agent badge

The titlebar agent badge is the single most distinctive Orca component. It shows a rounded-full pill containing two children only: a green dot (with an 18%-alpha halo) and the active-agent count. There is no text label in the trigger — the count alone is the label. The idle state (zero agents) de-emphasizes to muted-foreground and 55% opacity, with the halo removed from the dot.

The trigger is a button that opens a click-activated Popover, not a hover card, even though the anchor CSS class is named titlebar-agent-hovercard for historical reasons. The popover content lists active worktrees and their running agents, and a hide affordance at the bottom. The badge lives inside the titlebar drag region and explicitly opts out with -webkit-app-region: no-drag; descendant spans use pointer-events: none so the drag region never steals the cursor.

Inputs

Minimal chrome. 1px input border, 8px radius, 36px height, 14px horizontal padding, body-sm type. On focus, the border upgrades to ring and the 3px ring appears. No filled backgrounds in light mode; dark mode uses a subtle input/30 tint to keep the field visible against editor-surface.

Cards & Dialogs

Cards use rounded-lg, border, and card background. Dialogs add a soft drop shadow and close button. Both use 1624px internal padding. Dialog titles are text-lg font-semibold; descriptions use text-sm text-muted-foreground.

Sidebar

Default 280px, user-resizable 220500px, collapsible to 0. The sidebar is a vertical flex column with five fixed children in order: nav row, header, search bar, virtualized worktree list (the only scrolling region), and bottom toolbar. A 4px-wide right-edge hitbox drives the resize; the hitbox is transparent at rest, fills with ring/20 on hover, and ring/30 while dragging. Do not shrink the hitbox below 4px — Fitts's Law says a 1px target is effectively invisible to the cursor and the resize becomes frustrating to find.

Worktree item layout: branch name (13px, foreground) over path (11px, muted-foreground) with a 2px gap. The active worktree uses the sidebar-accent fill (not sidebar-primary, and not a left-border bar). Collapsing the sidebar animates width over 200ms.

Diff comments

A specific editor component that deserves its own token set because it overlays Monaco. Saved notes use a foreground @ 5% tint over editor-surface with a 3px left accent bar and a subtle drop shadow; popovers (entering state) share the same treatment with a stronger shadow so they visibly lift off the diff. Dark-mode uses 6% instead of 5% tint so the absolute luminance delta matches light-mode.

Scrollbars

Two variants:

  • Sleek (default): 12px track, thumb as muted-foreground @ 28% rising to 48% on parent hover, 0px radius, 3px padding.
  • Editor: 14px track, rgba(121,121,121,0.4) thumb with 7px radius — matches Monaco's native scrollbar so embedded editor panes feel continuous with surrounding chrome.

Some surfaces (terminal tab strip) hide scrollbars entirely to prevent drag-time flicker.

Do's and Don'ts

  • Do reserve the green agent dot for genuinely active work. An idle agent must never show green — a user glancing at the titlebar should learn "something is happening" in under half a second.

  • Do use muted-foreground for metadata (paths, timestamps, counts). If you're tempted to use foreground for a label, ask whether the user needs to read it or just needs to know it's there.

  • Do stay on the 4px grid. Most spacing bugs in Orca have been off-grid padding (10px, 14px) breaking alignment with adjacent panes.

  • Do let borders do the work of shadows. Add a shadow only when an element genuinely floats above others (popovers, dialogs).

  • Do honor the Why: comments in main.css. Several visual choices there (diff-comment card tint %, titlebar pointer-events, find-widget direction) encode past bugs; don't casually revert them.

  • Don't introduce new chromatic accents. The product chrome is neutral-only; color is reserved for state (red = destructive, green = running, blue accents = dark-mode active workspace, git decoration colors = source control).

  • Don't mix radii on the same object. A card and its internal buttons should share a consistent soft-rectangular family.

  • Don't use body weight (400) for buttons, badges, or other interactive atoms. Interactive type is 500600.

  • Don't use drop shadows to separate adjacent panes — that's what border is for. Reserve shadow for true overlays.

  • Don't add a third scrollbar style. If a surface feels like it needs one, it probably needs scrollbar-sleek with different padding.

  • Don't put destructive red next to the agent green. A screen that shows both at the same time is telling the user two urgent things at once, which almost always means one of them isn't actually urgent.

  • Don't place destructive buttons in the titlebar, right-sidebar toolbar, or any top-global chrome. Because the agent-activity badge (green) lives permanently in the titlebar, a top-chrome destructive action would force the two signal colors into constant co-occurrence. Destructive actions belong at the bottom-right of dialogs, at the end of a form, or inside a context menu — structurally isolated from the global activity indicator.