mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-04-25 00:51:20 +00:00
Dashboard themes now control typography and layout, not just colors. Each built-in theme picks its own fonts, base size, radius, and density so switching produces visible changes beyond hue. Schema additions (per theme): - typography — fontSans, fontMono, fontDisplay, fontUrl, baseSize, lineHeight, letterSpacing. fontUrl is injected as <link> on switch so Google/Bunny/self-hosted stylesheets all work. - layout — radius (any CSS length) and density (compact | comfortable | spacious, multiplies Tailwind spacing). - colorOverrides (optional) — pin individual shadcn tokens that would otherwise derive from the palette. Built-in themes are now distinct beyond palette: - default — system stack, 15px, 0.5rem radius, comfortable - midnight — Inter + JetBrains Mono, 14px, 0.75rem, comfortable - ember — Spectral (serif) + IBM Plex Mono, 15px, 0.25rem - mono — IBM Plex Sans + Mono, 13px, 0 radius, compact - cyberpunk— Share Tech Mono everywhere, 14px, 0 radius, compact - rose — Fraunces (serif) + DM Mono, 16px, 1rem, spacious Also fixes two bugs: 1. Custom user themes silently fell back to default. ThemeProvider only applied BUILTIN_THEMES[name], so YAML files in ~/.hermes/dashboard-themes/ showed in the picker but did nothing. Server now ships the full normalised definition; client applies it. 2. Docs documented a 21-token flat colors schema that never matched the code (applyPalette reads a 3-layer palette). Rewrote the Themes section against the actual shape. Implementation: - web/src/themes/types.ts: extend DashboardTheme with typography, layout, colorOverrides; ThemeListEntry carries optional definition. - web/src/themes/presets.ts: 6 built-ins with distinct typography+layout. - web/src/themes/context.tsx: applyTheme() writes palette+typography+ layout+overrides as CSS vars, injects fontUrl stylesheet, fixes the fallback-to-default bug via resolveTheme(name). - web/src/index.css: html/body/code read the new theme-font vars; --radius-sm/md/lg/xl derive from --theme-radius; --spacing scales with --theme-spacing-mul so Tailwind utilities shift with density. - hermes_cli/web_server.py: _normalise_theme_definition() parses loose YAML (bare hex strings, partial blocks) into the canonical wire shape; /api/dashboard/themes ships full definitions for user themes. - tests/hermes_cli/test_web_server.py: 16 new tests covering the normaliser and discovery (rejection cases, clamping, defaults). - website/docs/user-guide/features/web-dashboard.md: rewrite Themes section with real schema, per-model tables, full YAML example.
164 lines
5.9 KiB
CSS
164 lines
5.9 KiB
CSS
@import 'tailwindcss';
|
|
@import '@nous-research/ui/styles/globals.css';
|
|
|
|
/* Scan the published design-system bundle so its utility classes survive
|
|
Tailwind's JIT purge. */
|
|
@source '../node_modules/@nous-research/ui/dist';
|
|
|
|
/* ------------------------------------------------------------------ */
|
|
/* Hermes Agent — Nous DS with the LENS_0 (Hermes teal) lens applied */
|
|
/* statically. Mirrors nousnet-web/(hermes-agent)/layout.tsx so the */
|
|
/* canonical Hermes palette is the default — teal canvas + cream */
|
|
/* accent — without relying on leva/gsap at runtime. */
|
|
/* ------------------------------------------------------------------ */
|
|
|
|
:root {
|
|
/* LENS_0 — from design-language/src/ui/components/overlays/index.tsx.
|
|
These are the defaults for the `default` (Hermes Teal) dashboard theme;
|
|
ThemeProvider rewrites them as inline styles when a user switches themes. */
|
|
--foreground: color-mix(in srgb, #ffffff 0%, transparent);
|
|
--foreground-base: #ffffff;
|
|
--foreground-alpha: 0;
|
|
--midground: color-mix(in srgb, #ffe6cb 100%, transparent);
|
|
--midground-base: #ffe6cb;
|
|
--midground-alpha: 1;
|
|
--background: color-mix(in srgb, #041c1c 100%, transparent);
|
|
--background-base: #041c1c;
|
|
--background-alpha: 1;
|
|
|
|
/* Consumed by <Backdrop />; also theme-switchable. */
|
|
--warm-glow: rgba(255, 189, 56, 0.35);
|
|
--noise-opacity-mul: 1;
|
|
|
|
/* Typography tokens — rewritten by ThemeProvider. Defaults match the
|
|
system stack so themes that don't override look native. */
|
|
--theme-font-sans: system-ui, -apple-system, "Segoe UI", Roboto,
|
|
"Helvetica Neue", Arial, sans-serif;
|
|
--theme-font-mono: ui-monospace, "SF Mono", "Cascadia Mono", Menlo,
|
|
Consolas, monospace;
|
|
--theme-font-display: var(--theme-font-sans);
|
|
--theme-base-size: 15px;
|
|
--theme-line-height: 1.55;
|
|
--theme-letter-spacing: 0;
|
|
|
|
/* Layout tokens. */
|
|
--radius: 0.5rem;
|
|
--theme-radius: 0.5rem;
|
|
--theme-spacing-mul: 1;
|
|
--theme-density: comfortable;
|
|
}
|
|
|
|
/* Theme tokens cascade into the document root so every descendant inherits
|
|
the font stack, base size, and letter spacing without explicit calls. */
|
|
html {
|
|
font-family: var(--theme-font-sans);
|
|
font-size: var(--theme-base-size);
|
|
line-height: var(--theme-line-height);
|
|
letter-spacing: var(--theme-letter-spacing);
|
|
}
|
|
|
|
body {
|
|
font-family: var(--theme-font-sans);
|
|
}
|
|
|
|
code, kbd, pre, samp, .font-mono, .font-mono-ui {
|
|
font-family: var(--theme-font-mono);
|
|
}
|
|
|
|
/* Density: scale the shadcn spacing utilities via a multiplier. The DS
|
|
components use `p-N` / `gap-N` / `space-*` classes which resolve against
|
|
Tailwind's spacing scale; multiplying `--spacing` at :root scales them
|
|
all proportionally in Tailwind v4. */
|
|
@theme inline {
|
|
--spacing: calc(0.25rem * var(--theme-spacing-mul, 1));
|
|
}
|
|
|
|
/* Nousnet's hermes-agent layout bumps `small` and `code` to readable
|
|
dashboard sizes. Keep in sync. */
|
|
small { font-size: 1.0625rem; }
|
|
code { font-size: 0.875rem; }
|
|
|
|
/* Shadcn-compat tokens.
|
|
The dashboard's page code predates the Nous DS and uses shadcn-style
|
|
utility classes (bg-card, text-muted-foreground, border-border, etc.)
|
|
extensively. Rather than rewrite every call site, we expose those
|
|
tokens on top of the Nous palette so classes continue to resolve. */
|
|
@theme inline {
|
|
/* Remap foreground to midground so `text-foreground` / `bg-foreground`
|
|
stay visible — in LENS_0, `--foreground` itself has alpha 0. */
|
|
--color-foreground: var(--midground);
|
|
|
|
--color-card: color-mix(in srgb, var(--midground-base) 4%, var(--background-base));
|
|
--color-card-foreground: var(--midground);
|
|
--color-primary: var(--midground);
|
|
--color-primary-foreground: var(--background-base);
|
|
--color-secondary: color-mix(in srgb, var(--midground-base) 6%, var(--background-base));
|
|
--color-secondary-foreground: var(--midground);
|
|
--color-muted: color-mix(in srgb, var(--midground-base) 8%, var(--background-base));
|
|
--color-muted-foreground: color-mix(in srgb, var(--midground-base) 55%, transparent);
|
|
--color-accent: color-mix(in srgb, var(--midground-base) 10%, var(--background-base));
|
|
--color-accent-foreground: var(--midground);
|
|
--color-destructive: #fb2c36;
|
|
--color-destructive-foreground: #ffffff;
|
|
--color-success: #4ade80;
|
|
--color-warning: #ffbd38;
|
|
--color-border: color-mix(in srgb, var(--midground-base) 15%, transparent);
|
|
--color-input: color-mix(in srgb, var(--midground-base) 15%, transparent);
|
|
--color-ring: var(--midground);
|
|
--color-popover: color-mix(in srgb, var(--midground-base) 4%, var(--background-base));
|
|
--color-popover-foreground: var(--midground);
|
|
|
|
--radius-sm: calc(var(--theme-radius) - 4px);
|
|
--radius-md: calc(var(--theme-radius) - 2px);
|
|
--radius-lg: var(--theme-radius);
|
|
--radius-xl: calc(var(--theme-radius) + 4px);
|
|
}
|
|
|
|
|
|
/* Toast animations used by `components/Toast.tsx`. */
|
|
@keyframes toast-in {
|
|
from { opacity: 0; transform: translateX(16px); }
|
|
to { opacity: 1; transform: translateX(0); }
|
|
}
|
|
@keyframes toast-out {
|
|
from { opacity: 1; transform: translateX(0); }
|
|
to { opacity: 0; transform: translateX(16px); }
|
|
}
|
|
|
|
/* Hide scrollbar utility — used by the header's overflow-x nav row. */
|
|
.scrollbar-none {
|
|
-ms-overflow-style: none;
|
|
scrollbar-width: none;
|
|
}
|
|
.scrollbar-none::-webkit-scrollbar {
|
|
display: none;
|
|
}
|
|
|
|
/* Plus-lighter blend used by logos/titles for a subtle glow. */
|
|
.blend-lighter {
|
|
mix-blend-mode: plus-lighter;
|
|
}
|
|
|
|
/* System UI-monospace stack — distinct from `font-courier` (Courier
|
|
Prime), used for dense data readouts where the display font would
|
|
break the grid. Routes through the theme's mono stack so themes
|
|
with a different monospace (JetBrains Mono, IBM Plex Mono, etc.)
|
|
still apply here. */
|
|
.font-mono-ui {
|
|
font-family: var(--theme-font-mono);
|
|
}
|
|
|
|
/* Subtle grain overlay for badges. */
|
|
.grain {
|
|
position: relative;
|
|
}
|
|
.grain::after {
|
|
content: '';
|
|
position: absolute;
|
|
inset: 0;
|
|
opacity: 0.12;
|
|
pointer-events: none;
|
|
background: repeating-conic-gradient(currentColor 0% 25%, #0000 0% 50%) 0 0 /
|
|
2px 2px;
|
|
}
|
|
|