docs: align uiux demo theme controls

This commit is contained in:
Frank Song
2026-05-18 12:50:25 +08:00
parent e6be01c4dd
commit 46029e0b1c
8 changed files with 124 additions and 28 deletions

View File

@@ -2,6 +2,11 @@
## [Unreleased]
### Documentation
- Align the `docs/ui-ux/` demo appearance controls with the current Theme + Skin
model, replacing the stale `data-theme`-only buttons and legacy theme names.
## [v0.51.89] — 2026-05-18 — Release BM (stage-382 — 6-PR full sweep batch — runtime adapter approval/clarify seam + SOUL.md memory panel + #1855 resolve_model_provider fast-path + PWA sidebar spinner fix + /model active-provider preference + contributor contract docs index)
### Changed

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

View File

@@ -1,5 +1,5 @@
<!doctype html>
<html lang="en" data-theme="slate">
<html lang="en" class="dark" data-skin="slate">
<head>
<meta charset="utf-8">
<title>Hermes WebUI — Messages UI Inventory</title>
@@ -54,14 +54,21 @@
<div class="doc-title">Hermes WebUI — Messages UI Inventory<small>Every message-area element &amp; combination, wired to the real <code>static/style.css</code>. &nbsp;·&nbsp; <a href="./two-stage-proposal.html" style="color:var(--blue);text-decoration:none;">Two-stage proposal (#536) →</a></small></div>
<div class="doc-toggles">
<strong style="font-size:10px;color:var(--muted);letter-spacing:.08em;text-transform:uppercase;align-self:center;margin-right:4px;">Theme</strong>
<button data-theme-btn="default">Default</button>
<button data-theme-btn="slate" class="on">Slate</button>
<button data-theme-btn="light">Light</button>
<button data-theme-btn="solarized">Solarized</button>
<button data-theme-btn="monokai">Monokai</button>
<button data-theme-btn="nord">Nord</button>
<button data-theme-btn="oled">OLED</button>
<button data-mode-btn="system">System</button>
<button data-mode-btn="dark" class="on">Dark</button>
<button data-mode-btn="light">Light</button>
<span style="width:1px;height:18px;background:var(--border);margin:0 4px;align-self:center;"></span>
<strong style="font-size:10px;color:var(--muted);letter-spacing:.08em;text-transform:uppercase;align-self:center;margin-right:4px;">Skin</strong>
<button data-skin-btn="default">Default</button>
<button data-skin-btn="ares">Ares</button>
<button data-skin-btn="mono">Mono</button>
<button data-skin-btn="slate" class="on">Slate</button>
<button data-skin-btn="poseidon">Poseidon</button>
<button data-skin-btn="sisyphus">Sisyphus</button>
<button data-skin-btn="charizard">Charizard</button>
<button data-skin-btn="sienna">Sienna</button>
<button data-skin-btn="catppuccin">Catppuccin</button>
<button data-skin-btn="nous">Nous</button>
</div>
</header>
@@ -817,15 +824,33 @@ Run typecheck to confirm, then patch.</pre></div>
onload="renderMathInElement(document.body,{delimiters:[{left:'$$',right:'$$',display:true},{left:'\\[',right:'\\]',display:true},{left:'\\(',right:'\\)',display:false},{left:'$',right:'$',display:false}],throwOnError:false});"></script>
<script>
// Theme picker
document.querySelectorAll('[data-theme-btn]').forEach(btn => {
// Appearance picker (matches the real app contract: theme class + skin data attribute)
let docTheme = 'dark';
let docSkin = 'slate';
const docThemeMq = window.matchMedia('(prefers-color-scheme: dark)');
function applyDocAppearance() {
const resolvedTheme = docTheme === 'system' ? (docThemeMq.matches ? 'dark' : 'light') : docTheme;
document.documentElement.classList.toggle('dark', resolvedTheme === 'dark');
if (docSkin === 'default') document.documentElement.removeAttribute('data-skin');
else document.documentElement.dataset.skin = docSkin;
}
document.querySelectorAll('[data-mode-btn]').forEach(btn => {
btn.addEventListener('click', () => {
const t = btn.dataset.themeBtn;
if (t === 'default') document.documentElement.removeAttribute('data-theme');
else document.documentElement.setAttribute('data-theme', t);
document.querySelectorAll('[data-theme-btn]').forEach(b => b.classList.toggle('on', b === btn));
docTheme = btn.dataset.modeBtn;
applyDocAppearance();
document.querySelectorAll('[data-mode-btn]').forEach(b => b.classList.toggle('on', b === btn));
});
});
document.querySelectorAll('[data-skin-btn]').forEach(btn => {
btn.addEventListener('click', () => {
docSkin = btn.dataset.skinBtn;
applyDocAppearance();
document.querySelectorAll('[data-skin-btn]').forEach(b => b.classList.toggle('on', b === btn));
});
});
if (docThemeMq.addEventListener) {
docThemeMq.addEventListener('change', () => { if (docTheme === 'system') applyDocAppearance(); });
}
// Bubble-layout toggle
// Thinking / tool-card click-to-toggle (so the demo feels live)

View File

@@ -1,5 +1,5 @@
<!doctype html>
<html lang="en" data-theme="slate">
<html lang="en" class="dark" data-skin="slate">
<head>
<meta charset="utf-8">
<title>Hermes WebUI — Two-Stage Chat Proposal (Issue #536)</title>
@@ -167,13 +167,21 @@
</div>
<div class="doc-toggles">
<strong style="font-size:10px;color:var(--muted);letter-spacing:.08em;text-transform:uppercase;align-self:center;margin-right:4px;">Theme</strong>
<button data-theme-btn="default">Default</button>
<button data-theme-btn="slate" class="on">Slate</button>
<button data-theme-btn="light">Light</button>
<button data-theme-btn="solarized">Solarized</button>
<button data-theme-btn="monokai">Monokai</button>
<button data-theme-btn="nord">Nord</button>
<button data-theme-btn="oled">OLED</button>
<button data-mode-btn="system">System</button>
<button data-mode-btn="dark" class="on">Dark</button>
<button data-mode-btn="light">Light</button>
<span style="width:1px;height:18px;background:var(--border);margin:0 4px;align-self:center;"></span>
<strong style="font-size:10px;color:var(--muted);letter-spacing:.08em;text-transform:uppercase;align-self:center;margin-right:4px;">Skin</strong>
<button data-skin-btn="default">Default</button>
<button data-skin-btn="ares">Ares</button>
<button data-skin-btn="mono">Mono</button>
<button data-skin-btn="slate" class="on">Slate</button>
<button data-skin-btn="poseidon">Poseidon</button>
<button data-skin-btn="sisyphus">Sisyphus</button>
<button data-skin-btn="charizard">Charizard</button>
<button data-skin-btn="sienna">Sienna</button>
<button data-skin-btn="catppuccin">Catppuccin</button>
<button data-skin-btn="nous">Nous</button>
</div>
</header>
@@ -698,15 +706,33 @@ tool_calls get attached before save.</pre></div>
</main>
<script>
// Theme picker (matches index.html)
document.querySelectorAll('[data-theme-btn]').forEach(btn => {
// Appearance picker (matches the real app contract: theme class + skin data attribute)
let docTheme = 'dark';
let docSkin = 'slate';
const docThemeMq = window.matchMedia('(prefers-color-scheme: dark)');
function applyDocAppearance() {
const resolvedTheme = docTheme === 'system' ? (docThemeMq.matches ? 'dark' : 'light') : docTheme;
document.documentElement.classList.toggle('dark', resolvedTheme === 'dark');
if (docSkin === 'default') document.documentElement.removeAttribute('data-skin');
else document.documentElement.dataset.skin = docSkin;
}
document.querySelectorAll('[data-mode-btn]').forEach(btn => {
btn.addEventListener('click', () => {
const t = btn.dataset.themeBtn;
if (t === 'default') document.documentElement.removeAttribute('data-theme');
else document.documentElement.setAttribute('data-theme', t);
document.querySelectorAll('[data-theme-btn]').forEach(b => b.classList.toggle('on', b === btn));
docTheme = btn.dataset.modeBtn;
applyDocAppearance();
document.querySelectorAll('[data-mode-btn]').forEach(b => b.classList.toggle('on', b === btn));
});
});
document.querySelectorAll('[data-skin-btn]').forEach(btn => {
btn.addEventListener('click', () => {
docSkin = btn.dataset.skinBtn;
applyDocAppearance();
document.querySelectorAll('[data-skin-btn]').forEach(b => b.classList.toggle('on', b === btn));
});
});
if (docThemeMq.addEventListener) {
docThemeMq.addEventListener('change', () => { if (docTheme === 'system') applyDocAppearance(); });
}
// Existing thinking/tool cards click-to-toggle.
document.querySelectorAll('.thinking-card-header, .tool-card-header').forEach(h => {

View File

@@ -0,0 +1,40 @@
from pathlib import Path
DEMO_DOCS = [
Path("docs/ui-ux/index.html"),
Path("docs/ui-ux/two-stage-proposal.html"),
]
THEME_VALUES = ("system", "dark", "light")
SKIN_VALUES = (
"default",
"ares",
"mono",
"slate",
"poseidon",
"sisyphus",
"charizard",
"sienna",
"catppuccin",
"nous",
)
LEGACY_THEME_LABELS = ("Solarized", "Monokai", "Nord", "OLED")
def test_uiux_demo_docs_use_current_theme_skin_axes():
for doc_path in DEMO_DOCS:
html = doc_path.read_text()
assert 'data-theme="' not in html, f"{doc_path} should not use legacy data-theme"
assert 'class="dark" data-skin="slate"' in html
assert "classList.toggle('dark'" in html
assert "dataset.skin" in html
for theme in THEME_VALUES:
assert f'data-mode-btn="{theme}"' in html
for skin in SKIN_VALUES:
assert f'data-skin-btn="{skin}"' in html
for label in LEGACY_THEME_LABELS:
assert f">{label}<" not in html