Files
orca/docs/styleguide/color.md
T
NeilandClaude daa11df406 feat(themes): public tokens for diffs, git status, tabs, dividers, rows, links (#36578)
* feat(themes): public tokens for diffs, git status, tabs, dividers, rows, links

Adds 29 public app theme tokens (diff, git decorations, tab bar, split
divider, current workspace row, host badge, chat bubble, text link), each
falling back to today's built-in color or CSS chain so existing themes and
built-ins render the same. Monaco's diff editor now paints from the diff
tokens, with sharper default diff tints (from #34698) and a readable dark
ignored-file color. The contrast gate learns one-sided drops, translucent
surfaces checked over their base, and main.css chains for half-set pairs.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(themes): check omitted diff tints, chat bubbles and dark host badges as painted

The contrast gate now derives an omitted diff tint from the theme's hue (and
drops the hue when its tint hides code), checks chat bubbles against chat's
mixed foreground on the chat canvas, and models the dark host badge at 80%
accent. The main.css fallback table moves to plugin-theme-css-fallbacks.ts.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(themes): blame a diff hue only for tints it painted, and check chat diff rows

A diff tint the theme set itself no longer drops the theme's hue when it
fails, and chat diff rows (hue-mixed text on the line tint over the chat
canvas) are now checked too.

Co-Authored-By: Claude <noreply@anthropic.com>

* fix(themes): new theme tokens only expose colors; unthemed surfaces paint exactly as before

Every new token now falls back to the exact value its surface used before:
- Diff hues default to the git decoration colors at the previous per-side
  percentages, and chat diff text keeps its 70% mix.
- Monaco's diff view, overview ruler and links keep Monaco's stock colors
  unless the theme painted a diff or link token. The colors go through the
  derived Monaco theme instead of a global CSS override.
- --text-link has no :root default; each link rule keeps its old literal as
  the fallback, including the markdown-light/-dark preview split and the
  always-#58a6ff Monaco doc link.
- Tab bar, tab text and indicator fall back per element (bg-card,
  text-foreground, ...) instead of through :root aliases.
- Dark --git-decoration-ignored goes back to #6e6e6e (#35910 ships separately).

The contrast gate skips checks that have no theme token to drop, so themes
that set only older tokens pay no extra probes.

* perf(themes): contrast check skips ring checks the theme didn't set and precomputes drop lists

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-31 19:20:51 -07:00

5.4 KiB

Color roles in detail

Deep reference for docs/STYLEGUIDE.md. Values live in src/renderer/src/assets/main.css (:root, .dark); this file documents roles only.

Role table

Tokens come in pairs: a surface and a foreground that meets contrast on it. Always use them together.

Role Use it for Don't use it for
background / foreground App canvas, default text Cards, popovers, sidebar (have their own)
card / card-foreground Panels lifted off the canvas The canvas itself
popover / popover-foreground Floating menus, dropdowns, hovercards Inline UI
primary / primary-foreground The single affirmative action in a flow (Save, Confirm) Decorative accents; hover states; secondary actions
secondary / secondary-foreground Lower-emphasis actions next to a primary The affirmative action
muted / muted-foreground De-emphasized text, captions, placeholders, disabled chrome Body copy; primary actions
accent / accent-foreground Hover/active backgrounds for ghost buttons and list rows Solid filled buttons (use secondary instead)
destructive / destructive-foreground Delete, discard, irreversible-action buttons; error states Cancel buttons (Cancel is not destructive)
border All hairlines: dividers, input outlines, card edges Heavy emphasis; that's ring
input Form field background only Anywhere outside form fields
ring Focus-visible outlines, active selection halos Persistent decoration
sidebar (+ variants) The worktree sidebar and its children Other panels
editor-surface Background of Monaco / markdown editor panes App chrome

The sidebar family (--sidebar, --sidebar-foreground, --sidebar-primary, --sidebar-primary-foreground, --sidebar-accent, --sidebar-accent-foreground, --sidebar-border, --sidebar-ring) is for use inside the worktree sidebar so its hover/selected/focus states stay consistent and don't bleed into other panels.

editor-surface is its own token (not just background) because Monaco and the markdown editor have a slightly darker surface in dark mode to match common editor conventions; reach for it whenever you're rendering an editor pane.

Git decoration colors

For diff status, file-tree decorations, and the changes view, use the --git-decoration-* tokens: added, modified, deleted, renamed, untracked, copied, ignored. The palette mirrors the conventions users already know from other editors, so they aren't surprised.

Use these only for git status. Don't reuse them for unrelated state colors — that breaks the convention.

Diff hunks (line, changed-character and gutter tints in chat diffs and Monaco's diff editor) use --diff-added / --diff-removed and their -background, -emphasis and -gutter tints instead. The hues default to the matching decoration colors, so themes can tune diffs separately from file status. Diff text in chat uses text-chat-diff-added / text-chat-diff-removed.

List rows: hover, selected, current

A common point of drift. Use these conventions for any list-style row (worktrees, command palette items, settings nav):

  • Idle: transparent background.
  • Hover: bg-accent (in the worktree sidebar, bg-sidebar-accent).
  • Keyboard-selected (cmdk highlight): do not rely on flat bg-accent alone on light popover/dialog surfaces — light --accent is nearly identical to --background, so the cursor vanishes. Use the jump-palette recipe in main.css (.jump-palette-item[data-selected='true']): color-mix foreground into background plus an inset ring. Expose the mix as --jump-palette-selection-surface when nested cutouts (status pips) must match. The data-selected attribute is set by cmdk automatically.
  • Persistent "current" / "active" row (e.g. the worktree the user is viewing): also bg-accent, plus a data-current="true" attribute so CSS or future styling can distinguish it from the cmdk highlight.
  • Don't: hardcode bg-[#ededed] / bg-[#333333] or invent a "selected" color. Mix from existing tokens (foreground/background/accent) so light/dark stay aligned.

Color mixing

When you need a tint (e.g. a 12% primary wash on hover), use color-mix against the existing token, not a new hex. This keeps light/dark parity automatic:

background: color-mix(in srgb, var(--primary) 12%, var(--background));