From 0f8ba4d8d3db170152801fb879951c7b59ebe1a1 Mon Sep 17 00:00:00 2001 From: Michael De Gols Date: Mon, 11 May 2026 18:35:12 +0200 Subject: [PATCH] =?UTF-8?q?docs(themes):=20align=20THEMES.md=20with=20Them?= =?UTF-8?q?e=20=C3=97=20Skin=20architecture?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit THEMES.md still described the pre-#627 model where each theme was a monolithic palette name (Dark, Light, Slate, Solarized Dark, Monokai, Nord, OLED). The current architecture splits appearance into two orthogonal pickers: - Theme (System / Dark / Light) — applied as `.dark` class on - Skin (8 named accent palettes) — applied as `data-skin` attribute Rewrite the doc to: - Open with the Theme × Skin separation and how they combine - List the 3 themes and 8 actual skins shipped in static/style.css (default, ares, mono, slate, poseidon, sisyphus, charizard, sienna), with the same descriptive tone as the original - Replace "Creating a Custom Theme" with "Creating a Custom Skin" as the primary extension point, with paired light + dark CSS variants - Note the WebUI extensions surface (docs/EXTENSIONS.md) as a no-fork path for self-hosted custom skins - Update internals to reflect classList.toggle('dark') + dataset.skin + dataset.fontSize instead of the old data-theme-only model - Add a brief Font Size section since it sits in the same picker - Keep a smaller Custom Theme section for the rare case someone wants to override the core palette, redirecting most users to skins Docs-only change; no code touched. Co-Authored-By: Claude Opus 4.7 (1M context) --- THEMES.md | 251 +++++++++++++++++++++++++++++------------------------- 1 file changed, 136 insertions(+), 115 deletions(-) diff --git a/THEMES.md b/THEMES.md index 3dc46b8c..466259b9 100644 --- a/THEMES.md +++ b/THEMES.md @@ -1,19 +1,31 @@ # Hermes Web UI — Themes -Hermes Web UI supports pluggable color themes. Seven themes ship built-in, and -you can create your own with pure CSS — no Python changes needed. +Hermes Web UI splits **appearance** into two independent pickers: + +- **Theme** — the mode: `System`, `Dark`, or `Light`. Drives the background, + text, surface, and chrome colors. +- **Skin** — the accent palette: eight named skins ship built-in. Drives only + the `--accent` family (active states, links, focus rings, primary actions). + +You pick one of each and they combine, so the look adapts to your environment +without losing your favorite accent — pure CSS, no Python changes needed. --- -## Switching Themes +## Switching Appearance -**Settings panel:** Click the gear icon, select a theme from the dropdown. The -preview is instant — the UI updates as you click through options. +**Settings panel:** Click the gear icon → **Appearance**. The **Theme** card +toggles Light/Dark/System; the **Skin** grid offers eight accent palettes. +Preview is instant — the UI updates as you click. -**Slash command:** Type `/theme dark` or `/theme light` in the composer. +**Slash command:** Type `/theme ` in the composer. The command accepts +both theme names (`system`, `dark`, `light`) and skin names (`default`, `ares`, +`mono`, `slate`, `poseidon`, `sisyphus`, `charizard`, `sienna`). It updates the +matching axis and leaves the other one alone. -**Themes persist** across page reloads and server restarts (stored in -`settings.json` server-side, with `localStorage` for flicker-free loading). +**Persistence:** Both choices are stored in `localStorage` for flicker-free +loading, and saved server-side via `POST /api/settings` (under `theme` and +`skin` keys in `settings.json`). --- @@ -21,125 +33,134 @@ preview is instant — the UI updates as you click through options. | Theme | Description | |-------|-------------| -| **Dark** (default) | Deep navy/indigo with muted blue accents. Easy on the eyes for long sessions. | -| **Light** | Warm off-white with dark text. High contrast for bright environments. | -| **Slate** | Warm charcoal, lighter than Dark. Easier on the eyes for extended use. | -| **Solarized Dark** | Ethan Schoonover's classic dark palette. Teal background, warm accents. | -| **Monokai** | Warm dark theme inspired by the Monokai editor scheme. Green/pink accents. | -| **Nord** | Arctic blue-gray palette from the Nord color system. Calm and minimal. | -| **OLED** | True black (#000) backgrounds for OLED displays. Minimizes glow and burn-in risk. | -| **Custom themes** | Any string accepted by `settings.json`, `POST /api/settings`, and `/theme` if added to the picker/command list. Pure CSS variables only. | +| **System** (default) | Follows the OS `prefers-color-scheme` preference and updates live. | +| **Dark** | Deep dark surfaces, low-glare for long sessions. | +| **Light** | Bright surfaces with dark text, high contrast for daylight environments. | + +The theme is applied as a class on ``: `.dark` is present for dark mode, +absent for light. System mode tracks the OS preference at runtime. + +--- + +## Built-in Skins + +| Skin | Description | +|------|-------------| +| **Default** | The original Hermes gold accent. Warm and understated. | +| **Ares** | Fiery red. High-energy and assertive. | +| **Mono** | Neutral gray. Distraction-free, for deep focus. | +| **Slate** | Slate blue-gray. Subtle and grown-up. | +| **Poseidon** | Ocean blue. Calm and focused for long sessions. | +| **Sisyphus** | Vivid purple. Distinctive without being loud. | +| **Charizard** | Warm orange. Energetic and easy on the eyes. | +| **Sienna** | Warm clay and sand earth palette. Soft and natural. | + +Each skin defines paired light + dark variants so it reads cleanly on either +theme. The skin is applied as `data-skin=""` on `` (the default +skin clears the attribute). + +--- + +## Creating a Custom Skin + +A skin is a small CSS block that overrides the accent variables for both the +light and dark variants: + +```css +/* Light variant */ +:root[data-skin="my-skin"] { + --accent: #2E7D32; /* Active states, links, primary buttons */ + --accent-hover: #1B5E20; /* Hover */ + --accent-bg: rgba(46,125,50,0.08); /* Soft tinted backgrounds */ + --accent-bg-strong: rgba(46,125,50,0.15); /* Highlighted backgrounds */ + --accent-text: #1B5E20; /* Text on accent bg */ +} + +/* Dark variant — usually lighter or more saturated for contrast */ +:root.dark[data-skin="my-skin"] { + --accent: #66BB6A; + --accent-hover: #43A047; + --accent-bg: rgba(102,187,106,0.08); + --accent-bg-strong: rgba(102,187,106,0.15); + --accent-text: #66BB6A; +} +``` + +Two ways to ship it: + +1. **In the repo (built-in):** add the block to `static/style.css`, register it + in the Settings skin picker (`static/index.html`) and in the `/theme` command + list (`static/commands.js`), then open a PR. + +2. **Self-hosted (no fork):** use the WebUI extensions surface — see + `docs/EXTENSIONS.md`. Drop your CSS in `HERMES_WEBUI_EXTENSION_DIR` and + declare it in `HERMES_WEBUI_EXTENSION_STYLESHEET_URLS`. No code changes + needed; the skin attribute can be set from your own JS. + +### Tips + +- **Test both themes.** A skin that pops on Dark can be illegible on Light. + Always check `:root[data-skin]` (light) *and* `:root.dark[data-skin]` (dark). +- **Pick contrasting `--accent-text` on `--accent-bg`.** The strong variant + appears behind small labels and chips; weak contrast there reads as blur. +- **The logo gradient uses `--accent` automatically**, so it adapts to your + skin without any extra work. +- **No server changes needed.** The `skin` setting in `settings.json` accepts + any string, so your custom skin name persists without code changes once you + load the CSS. --- ## Creating a Custom Theme -A theme is a CSS block that overrides the color variables. Add it to -`static/style.css` (or a separate file that you link after the main stylesheet). +A full custom *theme* (a different overall mood, not just an accent change) is +a larger task than a skin: it has to redefine the core palette variables +(`--bg`, `--surface`, `--text`, `--border`, `--code-bg`, and friends) for one +or both modes. The contract is defined in the top `:root` and `:root.dark` +blocks of `static/style.css` — start there. -### Step 1: Define your theme block - -Every color in the UI comes from these CSS variables: - -```css -:root[data-theme="your-theme-name"] { - /* Core palette */ - --bg: #1a1a2e; /* Main background */ - --sidebar: #16213e; /* Sidebar background */ - --border: rgba(255,255,255,0.08); /* Subtle borders */ - --border2: rgba(255,255,255,0.14); /* Stronger borders */ - --text: #e8e8f0; /* Primary text color */ - --muted: #8888aa; /* Secondary/muted text */ - --accent: #e94560; /* Accent color (errors, warnings, delete) */ - --blue: #7cb9ff; /* Primary action color (links, active states) */ - --gold: #c9a84c; /* Secondary accent (pinned items, gold highlights) */ - --code-bg: #0d1117; /* Code block background */ - - /* Surface and chrome (required for full theme polish) */ - --surface: #1a2535; /* Dropdowns, popups, toast, approval card */ - --topbar-bg: rgba(22,33,62,.98); /* Topbar background */ - --main-bg: rgba(26,26,46,0.5); /* Main chat area background */ - --input-bg: rgba(255,255,255,.04); /* Input/button subtle backgrounds */ - --hover-bg: rgba(255,255,255,.06); /* Hover state backgrounds */ - --focus-ring: rgba(124,185,255,.35); /* Focus border color */ - --focus-glow: rgba(124,185,255,.08); /* Focus box-shadow glow */ - - /* Typography (required for readable text across themes) */ - --strong: #fff; /* Bold text in messages */ - --em: #c9c9e8; /* Italic text in messages */ - --code-text: #f0c27f; /* Inline code text color */ - --code-inline-bg: rgba(0,0,0,.35); /* Inline code background */ - --pre-text: #e2e8f0; /* Code block text color */ -} -``` - -The **core palette** controls the overall mood. The **surface/chrome** and -**typography** variables are part of the standard theme contract — define all -of them for a complete theme. - -For **light themes**, you also need `:root[data-theme="name"]` overrides -for elements that use `rgba(255,255,255,.XX)` hover/border effects (these -are invisible on light backgrounds). See the built-in light theme for the -full pattern — it overrides ~45 selectors for proper dark-on-light contrast -on hover states, borders, chips, role labels, session items, and -interactive elements. - -### Step 2: Add it to the theme picker (optional) - -To make your theme appear in the Settings dropdown, add an `