* 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>
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-accentalone on light popover/dialog surfaces — light--accentis nearly identical to--background, so the cursor vanishes. Use the jump-palette recipe inmain.css(.jump-palette-item[data-selected='true']):color-mixforeground into background plus an inset ring. Expose the mix as--jump-palette-selection-surfacewhen nested cutouts (status pips) must match. Thedata-selectedattribute is set bycmdkautomatically. - Persistent "current" / "active" row (e.g. the worktree the user is viewing): also
bg-accent, plus adata-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));