hyperhive/docs/web-ui/css-vars.md
iris e70584b632 feat(frontend): split theme CSS vars into a standalone theme.css
Phase 1 of stylix integration (#1457): extract the Catppuccin palette
into a dedicated, separately-linked stylesheet so a theme swap can
replace just that file without rebuilding the rest of the frontend.

- shared/src/theme.css (new): the `:root` palette, moved out of
  base.css (which now holds only the body typography it references).
- shared/package.json: export `./theme.css`.
- dashboard/src/theme.css + agent/src/theme.css (new): one-line
  re-exports of @hive/shared/theme.css so each package's esbuild emits
  its own standalone `dist/static/theme.css` (palette is NOT inlined
  into the page bundles).
- both build.mjs: add theme.css to the CSS build list.
- every page (dashboard index/flow/logs, agent index/stats/screen):
  link `theme.css` first, ahead of the page CSS, so the `:root` vars
  resolve for everything.
- docs/web-ui/css-vars.md: document the split + the no-rebuild rationale.

Behaviour-neutral — same colours, just relocated. Verified both
`npm run build` outputs: theme.css emits standalone (383b) with the
palette; no `--*` palette defs duplicated into common.css/agent.css.

Phase 2 (nix derivation that swaps theme.css from stylix colours) is a
follow-up; touches nix/frontend.nix, coordinating with damocles.

Part of #1457.
2026-06-06 08:46:45 +02:00

3.1 KiB

CSS custom properties (theme variables)

All colour variables are declared once in frontend/packages/shared/src/theme.css under :root. Per-page stylesheets (common.css, dashboard.css, flow.css, logs.css, agent.css) must reference these names and must not redeclare them. (base.css holds only the shared body typography — it references the palette but no longer defines it.)

theme.css is deliberately a standalone stylesheet, not @imported into the page bundles: each package re-exports it (src/theme.css@import "@hive/shared/theme.css") so esbuild emits its own dist/static/theme.css, and every page links it first (<link rel="stylesheet" href=".../theme.css">) ahead of the page CSS. Because the palette lives in its own output file, a theme swap — e.g. a stylix-generated variant carrying the same variable names — can replace just that one file without rebuilding the rest of the frontend bundle.

Palette (theme.css)

Variable Hex Catppuccin Mocha Use
--bg #1e1e2e base page background
--bg-elev #181825 mantle elevated surfaces: floating dropdowns, popovers
--crust #11111b crust terminal / code block background
--fg #cdd6f4 text primary text colour
--muted #7f849c overlay1 secondary / dimmed text
--purple #cba6f7 mauve accent — active tabs, links, highlights
--purple-dim #45475a surface1 subtle borders, terminal chrome, badge backgrounds
--cyan #89dceb sky tool-use events, info accents
--blue #89b4fa blue links, interactive accent (distinct from sky)
--pink #f5c2e7 pink thinking events
--amber #fab387 peach warnings, pending / running state
--yellow #f9e2af yellow flash messages, mild warnings
--green #a6e3a1 green success, ok state
--red #f38ba8 red errors, fail state
--border #313244 surface0 general borders, hover/active backgrounds
--subtext0 #a6adc8 subtext0 secondary toolbar/status text; dimmer than --fg, lighter than --muted

Common mistakes

The Catppuccin colour names do not map 1:1 to the variable names. Variables to avoid (undefined — they will silently resolve to transparent / inherited):

Wrong Correct
--text --fg
--mauve --purple
--surface0 --bg-elev (float bg) or --border (border/hover)
--surface1 --border
--surface2 --purple-dim
--overlay0, --overlay1 --muted
--base, --mantle --bg, --bg-elev

Usage guide

Floating menus and dropdowns (e.g. agent context menu, tabbar overflow):

background: var(--bg-elev);
border: 1px solid var(--purple-dim);

Hover / active state backgrounds:

background: var(--border);

Active tab text / accent elements:

color: var(--purple);

Muted / meta text:

color: var(--muted);

Error / warning / success badges:

color: var(--red);    /* error */
color: var(--amber);  /* warning / running */
color: var(--green);  /* ok */