Files
webui/THEMES.md
Nathan Esquenazi 2eddef3275 fix: replace 30+ hardcoded dark-navy colors with theme CSS variables
Root cause: topbar, dropdowns, toast, approval card, tooltips, main area,
inputs, and hover states all used hardcoded rgba(22,33,62), #1a2535, etc.
These only looked correct on the Dark theme — all other themes showed
jarring dark-navy elements on non-navy backgrounds.

New CSS variables added to every theme block:
- --surface: dropdowns, popups, toast, approval card
- --topbar-bg: topbar background
- --main-bg: main chat area background
- --input-bg: subtle input/button backgrounds
- --hover-bg: hover state backgrounds
- --focus-ring / --focus-glow: focus border and box-shadow

Light theme now has proper light-colored surfaces, inputs, and hover
states instead of invisible white-on-white.

THEMES.md updated with all new variables documented.

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-04 21:43:53 -07:00

5.2 KiB

Hermes Web UI — Themes

Hermes Web UI supports pluggable color themes. Five themes ship built-in, and you can create your own with pure CSS — no Python changes needed.


Switching Themes

Settings panel: Click the gear icon, select a theme from the dropdown. The preview is instant — the UI updates as you click through options.

Slash command: Type /theme dark or /theme light in the composer.

Themes persist across page reloads and server restarts (stored in settings.json server-side, with localStorage for flicker-free loading).


Built-in Themes

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.

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).

Step 1: Define your theme block

Every color in the UI comes from these CSS variables:

: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 (optional — inherit from core palette if omitted) */
  --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 */
}

The core palette (first 10 variables) controls 90% of the UI. The surface/chrome variables are optional — if omitted, they fall back to defaults that work for dark themes. Light themes should override all of them.

Step 2: Add it to the theme picker (optional)

To make your theme appear in the Settings dropdown, add an <option> to the theme <select> in static/index.html:

<option value="your-theme-name">Your Theme Name</option>

And update the /theme command's valid theme list in static/commands.js.

Step 3: Test it

Switch to your theme via /theme your-theme-name or the Settings panel. Check these areas:

  • Sidebar session list (hover states, active state, project borders)
  • Message bubbles (user vs assistant styling)
  • Code blocks (background contrast, copy button visibility)
  • Tool cards (running indicator, expand/collapse)
  • Settings panel and login page
  • Mobile layout (hamburger sidebar, bottom nav)

Tips

  • Light themes need additional scrollbar overrides to avoid dark scrollbars on a light background. See the built-in light theme for the pattern.
  • The logo gradient uses --accent automatically, so it adapts to your theme without extra work.
  • Prism.js syntax highlighting uses its own CDN stylesheet (Tomorrow theme). It works well on dark themes; on light themes the contrast is acceptable but not perfect. Custom Prism theme support is planned for a future update.
  • No server changes needed. The theme setting in settings.json accepts any string — your custom theme name will persist without code changes.

How Themes Work Internally

  1. Each theme is a :root[data-theme="name"] CSS block that overrides variables.
  2. Switching themes sets document.documentElement.dataset.theme = name in JS.
  3. A tiny inline <script> in <head> reads localStorage before the stylesheet loads — this prevents a flash of the wrong theme on page load.
  4. The theme preference is saved server-side via POST /api/settings and loaded on boot via GET /api/settings.
  5. The /theme command and Settings dropdown both update the DOM, localStorage, and server settings simultaneously.

Contributing a Theme

To contribute a new built-in theme:

  1. Add your :root[data-theme="name"] block to static/style.css
  2. Add the <option> to the Settings panel in static/index.html
  3. Add the theme name to the valid list in cmdTheme() in static/commands.js
  4. Test on desktop and mobile
  5. Open a PR — themes are pure CSS additions with no backend changes needed