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.
This commit is contained in:
parent
a3e6585266
commit
e70584b632
14 changed files with 88 additions and 38 deletions
|
|
@ -1,11 +1,22 @@
|
|||
# CSS custom properties (theme variables)
|
||||
|
||||
All colour variables are declared **once** in
|
||||
`frontend/packages/shared/src/base.css` under `:root`.
|
||||
`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.
|
||||
names and must **not** redeclare them. (`base.css` holds only the
|
||||
shared `body` typography — it references the palette but no longer
|
||||
defines it.)
|
||||
|
||||
## Palette (`base.css`)
|
||||
`theme.css` is deliberately a **standalone** stylesheet, not `@import`ed
|
||||
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 |
|
||||
|---|---|---|---|
|
||||
|
|
|
|||
|
|
@ -43,15 +43,19 @@ await build({
|
|||
logLevel: 'info',
|
||||
});
|
||||
|
||||
// Bundle the CSS — the @import lines pull in shared/base.css and
|
||||
// shared/terminal.css from the @hive/shared workspace dep.
|
||||
await build({
|
||||
entryPoints: [src('agent.css')],
|
||||
outfile: staticDir('agent.css'),
|
||||
bundle: true,
|
||||
loader: { '.css': 'css' },
|
||||
logLevel: 'info',
|
||||
});
|
||||
// Bundle the CSS. `theme.css` re-exports the standalone Catppuccin
|
||||
// palette (kept its own output file so a theme swap replaces only it,
|
||||
// no bundle rebuild); `agent.css`'s @import lines pull in shared
|
||||
// base.css + terminal.css from the @hive/shared workspace dep.
|
||||
for (const entry of ['theme.css', 'agent.css']) {
|
||||
await build({
|
||||
entryPoints: [src(entry)],
|
||||
outfile: staticDir(entry),
|
||||
bundle: true,
|
||||
loader: { '.css': 'css' },
|
||||
logLevel: 'info',
|
||||
});
|
||||
}
|
||||
|
||||
for (const html of ['index.html', 'stats.html', 'screen.html']) {
|
||||
copyFileSync(src(html), dist(html));
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>hyperhive agent</title>
|
||||
<link rel="icon" type="image/svg+xml" href="icon">
|
||||
<link rel="stylesheet" href="static/theme.css">
|
||||
<link rel="stylesheet" href="static/agent.css">
|
||||
</head>
|
||||
<body class="agent-shell">
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>screen</title>
|
||||
<link rel="icon" type="image/svg+xml" href="icon">
|
||||
<link rel="stylesheet" href="static/theme.css">
|
||||
<link rel="stylesheet" href="static/agent.css">
|
||||
</head>
|
||||
<body class="screen-shell">
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>hyperhive agent — stats</title>
|
||||
<link rel="icon" type="image/svg+xml" href="icon">
|
||||
<link rel="stylesheet" href="static/theme.css">
|
||||
<link rel="stylesheet" href="static/agent.css">
|
||||
</head>
|
||||
<body>
|
||||
|
|
|
|||
6
frontend/packages/agent/src/theme.css
Normal file
6
frontend/packages/agent/src/theme.css
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
/* Standalone theme bundle — re-exports the shared Catppuccin palette so
|
||||
esbuild emits it as its own `dist/static/theme.css`, linked first by
|
||||
every agent page. Kept separate from the page bundles so a theme swap
|
||||
(e.g. stylix) replaces only this file. See @hive/shared/theme.css +
|
||||
docs/web-ui/css-vars.md. */
|
||||
@import "@hive/shared/theme.css";
|
||||
|
|
@ -77,10 +77,11 @@ await build({
|
|||
});
|
||||
|
||||
// Bundle CSS — one entry per page. esbuild resolves @import including
|
||||
// the package re-exports from @hive/shared. Each page loads common.css
|
||||
// (shared typography, badges, buttons, inbox, side panel) plus its own
|
||||
// page-specific bundle.
|
||||
for (const entry of ['common.css', 'dashboard.css', 'flow.css', 'logs.css']) {
|
||||
// the package re-exports from @hive/shared. Each page loads theme.css
|
||||
// (the standalone Catppuccin palette — kept its own file so a theme
|
||||
// swap replaces only it) + common.css (shared typography, badges,
|
||||
// buttons, inbox, side panel) plus its own page-specific bundle.
|
||||
for (const entry of ['theme.css', 'common.css', 'dashboard.css', 'flow.css', 'logs.css']) {
|
||||
await build({
|
||||
entryPoints: [src(entry)],
|
||||
outfile: staticDir(entry),
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>hyperhive // FL0W</title>
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
||||
<link rel="stylesheet" href="/static/theme.css">
|
||||
<link rel="stylesheet" href="/static/common.css">
|
||||
<link rel="stylesheet" href="/static/flow.css">
|
||||
</head>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>hyperhive // h1ve-c0re</title>
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
||||
<link rel="stylesheet" href="/static/theme.css">
|
||||
<link rel="stylesheet" href="/static/common.css">
|
||||
<link rel="stylesheet" href="/static/dashboard.css">
|
||||
</head>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>hyperhive // LOGS</title>
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
|
||||
<link rel="stylesheet" href="/static/theme.css">
|
||||
<link rel="stylesheet" href="/static/common.css">
|
||||
<link rel="stylesheet" href="/static/logs.css">
|
||||
</head>
|
||||
|
|
|
|||
6
frontend/packages/dashboard/src/theme.css
Normal file
6
frontend/packages/dashboard/src/theme.css
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
/* Standalone theme bundle — re-exports the shared Catppuccin palette so
|
||||
esbuild emits it as its own `dist/static/theme.css`, linked first by
|
||||
every dashboard page. Kept separate from the page bundles so a theme
|
||||
swap (e.g. stylix) replaces only this file. See @hive/shared/theme.css
|
||||
+ docs/web-ui/css-vars.md. */
|
||||
@import "@hive/shared/theme.css";
|
||||
|
|
@ -8,6 +8,7 @@
|
|||
"exports": {
|
||||
".": "./src/index.js",
|
||||
"./terminal.js": "./src/terminal.js",
|
||||
"./theme.css": "./src/theme.css",
|
||||
"./base.css": "./src/base.css",
|
||||
"./terminal.css": "./src/terminal.css"
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,25 +1,10 @@
|
|||
/* Base palette + typography shared by the hive-c0re dashboard and the
|
||||
hive-ag3nt web UI. Catppuccin Mocha. Per-page stylesheets append on
|
||||
top of this and must NOT redeclare the colour variables — the whole
|
||||
point of pulling them out is one source of truth. */
|
||||
:root {
|
||||
--bg: #1e1e2e; /* base */
|
||||
--bg-elev: #181825; /* mantle */
|
||||
--crust: #11111b; /* crust — terminal background */
|
||||
--fg: #cdd6f4; /* text */
|
||||
--muted: #7f849c; /* overlay1 */
|
||||
--purple: #cba6f7; /* mauve */
|
||||
--purple-dim: #45475a;/* surface1 */
|
||||
--cyan: #89dceb; /* sky */
|
||||
--blue: #89b4fa; /* blue */
|
||||
--pink: #f5c2e7; /* pink */
|
||||
--amber: #fab387; /* peach */
|
||||
--yellow: #f9e2af; /* yellow */
|
||||
--green: #a6e3a1; /* green */
|
||||
--red: #f38ba8; /* red */
|
||||
--border: #313244; /* surface0 */
|
||||
--subtext0: #a6adc8; /* subtext0 — secondary/toolbar text, dimmer than --fg but lighter than --muted */
|
||||
}
|
||||
/* Base typography shared by the hive-c0re dashboard and the hive-ag3nt
|
||||
web UI. The colour variables it references (`--bg`, `--fg`, …) live in
|
||||
the standalone `theme.css` (Catppuccin Mocha), linked separately by
|
||||
every page BEFORE this file so the `:root` vars resolve — see
|
||||
`theme.css` + docs/web-ui/css-vars.md. Per-page stylesheets append on
|
||||
top of this and must NOT redeclare the colour variables; `theme.css`
|
||||
is the one source of truth. */
|
||||
body {
|
||||
background: var(--bg);
|
||||
color: var(--fg);
|
||||
|
|
|
|||
30
frontend/packages/shared/src/theme.css
Normal file
30
frontend/packages/shared/src/theme.css
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/* Theme colour variables (Catppuccin Mocha) — the single source of
|
||||
truth for the hive UI palette. Kept in a standalone file, linked as
|
||||
its own `<link rel="stylesheet" href=".../theme.css">` by every page
|
||||
BEFORE the page CSS, so the `:root` vars are defined for everything
|
||||
that references them (base typography, terminal, dashboard, agent).
|
||||
|
||||
Why standalone rather than `@import`ed into the page bundles: esbuild
|
||||
inlines `@import` at build time, which would bake the palette into
|
||||
every CSS bundle. Emitting `theme.css` as its own output file lets a
|
||||
theme swap (e.g. a stylix-generated variant carrying the same var
|
||||
names) replace just this one file without rebuilding the rest of the
|
||||
frontend. See docs/web-ui/css-vars.md. */
|
||||
:root {
|
||||
--bg: #1e1e2e; /* base */
|
||||
--bg-elev: #181825; /* mantle */
|
||||
--crust: #11111b; /* crust — terminal background */
|
||||
--fg: #cdd6f4; /* text */
|
||||
--muted: #7f849c; /* overlay1 */
|
||||
--purple: #cba6f7; /* mauve */
|
||||
--purple-dim: #45475a;/* surface1 */
|
||||
--cyan: #89dceb; /* sky */
|
||||
--blue: #89b4fa; /* blue */
|
||||
--pink: #f5c2e7; /* pink */
|
||||
--amber: #fab387; /* peach */
|
||||
--yellow: #f9e2af; /* yellow */
|
||||
--green: #a6e3a1; /* green */
|
||||
--red: #f38ba8; /* red */
|
||||
--border: #313244; /* surface0 */
|
||||
--subtext0: #a6adc8; /* subtext0 — secondary/toolbar text, dimmer than --fg but lighter than --muted */
|
||||
}
|
||||
Loading…
Reference in a new issue