mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-24 05:41:40 +00:00
feat(dashboard): expand themes to fonts, layout, density (#14725)
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.
This commit is contained in:
parent
8f5fee3e3e
commit
255ba5bf26
8 changed files with 898 additions and 92 deletions
|
|
@ -1,17 +1,43 @@
|
|||
import type { DashboardTheme } from "./types";
|
||||
import type { DashboardTheme, ThemeTypography, ThemeLayout } from "./types";
|
||||
|
||||
/**
|
||||
* Built-in dashboard themes.
|
||||
*
|
||||
* The `default` theme mirrors LENS_0 (canonical Hermes teal) exactly — the
|
||||
* same triplet `src/index.css` declares on `:root`. Applying it should be a
|
||||
* visual no-op; other themes override the triplet + warm-glow and let the DS
|
||||
* cascade handle every derived surface.
|
||||
* Each theme defines its own palette, typography, and layout so switching
|
||||
* themes produces visible changes beyond just color — fonts, density, and
|
||||
* corner-radius all shift to match the theme's personality.
|
||||
*
|
||||
* Theme names must stay in sync with the backend's
|
||||
* `_BUILTIN_DASHBOARD_THEMES` list in `hermes_cli/web_server.py`.
|
||||
*/
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Shared typography / layout presets
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/** Default system stack — neutral, safe fallback for every platform. */
|
||||
const SYSTEM_SANS =
|
||||
'system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif';
|
||||
const SYSTEM_MONO =
|
||||
'ui-monospace, "SF Mono", "Cascadia Mono", Menlo, Consolas, monospace';
|
||||
|
||||
const DEFAULT_TYPOGRAPHY: ThemeTypography = {
|
||||
fontSans: SYSTEM_SANS,
|
||||
fontMono: SYSTEM_MONO,
|
||||
baseSize: "15px",
|
||||
lineHeight: "1.55",
|
||||
letterSpacing: "0",
|
||||
};
|
||||
|
||||
const DEFAULT_LAYOUT: ThemeLayout = {
|
||||
radius: "0.5rem",
|
||||
density: "comfortable",
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Themes
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export const defaultTheme: DashboardTheme = {
|
||||
name: "default",
|
||||
label: "Hermes Teal",
|
||||
|
|
@ -23,6 +49,8 @@ export const defaultTheme: DashboardTheme = {
|
|||
warmGlow: "rgba(255, 189, 56, 0.35)",
|
||||
noiseOpacity: 1,
|
||||
},
|
||||
typography: DEFAULT_TYPOGRAPHY,
|
||||
layout: DEFAULT_LAYOUT,
|
||||
};
|
||||
|
||||
export const midnightTheme: DashboardTheme = {
|
||||
|
|
@ -36,6 +64,19 @@ export const midnightTheme: DashboardTheme = {
|
|||
warmGlow: "rgba(167, 139, 250, 0.32)",
|
||||
noiseOpacity: 0.8,
|
||||
},
|
||||
typography: {
|
||||
fontSans: `"Inter", ${SYSTEM_SANS}`,
|
||||
fontMono: `"JetBrains Mono", ${SYSTEM_MONO}`,
|
||||
fontUrl:
|
||||
"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;700&display=swap",
|
||||
baseSize: "14px",
|
||||
lineHeight: "1.6",
|
||||
letterSpacing: "-0.005em",
|
||||
},
|
||||
layout: {
|
||||
radius: "0.75rem",
|
||||
density: "comfortable",
|
||||
},
|
||||
};
|
||||
|
||||
export const emberTheme: DashboardTheme = {
|
||||
|
|
@ -49,6 +90,23 @@ export const emberTheme: DashboardTheme = {
|
|||
warmGlow: "rgba(249, 115, 22, 0.38)",
|
||||
noiseOpacity: 1,
|
||||
},
|
||||
typography: {
|
||||
fontSans: `"Spectral", Georgia, "Times New Roman", serif`,
|
||||
fontMono: `"IBM Plex Mono", ${SYSTEM_MONO}`,
|
||||
fontUrl:
|
||||
"https://fonts.googleapis.com/css2?family=Spectral:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500;700&display=swap",
|
||||
baseSize: "15px",
|
||||
lineHeight: "1.6",
|
||||
letterSpacing: "0",
|
||||
},
|
||||
layout: {
|
||||
radius: "0.25rem",
|
||||
density: "comfortable",
|
||||
},
|
||||
colorOverrides: {
|
||||
destructive: "#c92d0f",
|
||||
warning: "#f97316",
|
||||
},
|
||||
};
|
||||
|
||||
export const monoTheme: DashboardTheme = {
|
||||
|
|
@ -62,6 +120,19 @@ export const monoTheme: DashboardTheme = {
|
|||
warmGlow: "rgba(255, 255, 255, 0.1)",
|
||||
noiseOpacity: 0.6,
|
||||
},
|
||||
typography: {
|
||||
fontSans: `"IBM Plex Sans", ${SYSTEM_SANS}`,
|
||||
fontMono: `"IBM Plex Mono", ${SYSTEM_MONO}`,
|
||||
fontUrl:
|
||||
"https://fonts.googleapis.com/css2?family=IBM+Plex+Sans:wght@400;500;600&family=IBM+Plex+Mono:wght@400;500&display=swap",
|
||||
baseSize: "13px",
|
||||
lineHeight: "1.5",
|
||||
letterSpacing: "0",
|
||||
},
|
||||
layout: {
|
||||
radius: "0",
|
||||
density: "compact",
|
||||
},
|
||||
};
|
||||
|
||||
export const cyberpunkTheme: DashboardTheme = {
|
||||
|
|
@ -75,6 +146,24 @@ export const cyberpunkTheme: DashboardTheme = {
|
|||
warmGlow: "rgba(0, 255, 136, 0.22)",
|
||||
noiseOpacity: 1.2,
|
||||
},
|
||||
typography: {
|
||||
fontSans: `"Share Tech Mono", "JetBrains Mono", ${SYSTEM_MONO}`,
|
||||
fontMono: `"Share Tech Mono", "JetBrains Mono", ${SYSTEM_MONO}`,
|
||||
fontUrl:
|
||||
"https://fonts.googleapis.com/css2?family=Share+Tech+Mono&family=JetBrains+Mono:wght@400;700&display=swap",
|
||||
baseSize: "14px",
|
||||
lineHeight: "1.5",
|
||||
letterSpacing: "0.02em",
|
||||
},
|
||||
layout: {
|
||||
radius: "0",
|
||||
density: "compact",
|
||||
},
|
||||
colorOverrides: {
|
||||
success: "#00ff88",
|
||||
warning: "#ffd700",
|
||||
destructive: "#ff0055",
|
||||
},
|
||||
};
|
||||
|
||||
export const roseTheme: DashboardTheme = {
|
||||
|
|
@ -88,6 +177,19 @@ export const roseTheme: DashboardTheme = {
|
|||
warmGlow: "rgba(249, 168, 212, 0.3)",
|
||||
noiseOpacity: 0.9,
|
||||
},
|
||||
typography: {
|
||||
fontSans: `"Fraunces", Georgia, serif`,
|
||||
fontMono: `"DM Mono", ${SYSTEM_MONO}`,
|
||||
fontUrl:
|
||||
"https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght@9..144,400;9..144,500;9..144,600&family=DM+Mono:wght@400;500&display=swap",
|
||||
baseSize: "16px",
|
||||
lineHeight: "1.7",
|
||||
letterSpacing: "0",
|
||||
},
|
||||
layout: {
|
||||
radius: "1rem",
|
||||
density: "spacious",
|
||||
},
|
||||
};
|
||||
|
||||
export const BUILTIN_THEMES: Record<string, DashboardTheme> = {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue