Theme Authoring Skill
Goal
Plug a new color theme into the Playground so it appears in the header theme
picker, is remembered across sessions, and themes every surface (main graph,
designer preview, learn pages) — with no component or graph-rendering edits.
Read First
docs/theme-authoring-guide.md — full architecture, token table, gotchas, worked example.
src/store/appStore.ts — ThemeId, THEME_OPTIONS, DARK_BASED_THEMES, isDarkTheme, themeClass.
src/styles/app.css — the :root / .light-theme / .theme-aurora / .theme-crimson token blocks (copy the nearest one).
Intake Questions
Ask the user:
- Theme id (lowercase, e.g.
indigo) and display label (e.g. Indigo)?
- Dark-based or light-based? (Determines
DARK_BASED_THEMES membership and which block to copy.)
- Accent / signature color (used for the picker swatch and
--ms-blue* / --info)?
- Any specific surface, text, or graph colors, or should they be derived from the accent?
Procedure
Make all edits in src/store/appStore.ts and
src/styles/app.css. The guide's
"Add a theme in six steps" section has copy-paste snippets.
- Add the id to the
ThemeId union.
- Add a
THEME_OPTIONS entry: { id, label, swatch } (swatch = accent hex).
- If dark-based, add the id to
DARK_BASED_THEMES. If light-based, leave it out.
- Add a
themeClass() case:
- dark-based →
return 'theme-<id>';
- light-based →
return 'light-theme theme-<id>'; (layer over the light base).
- Add a
.theme-<id> block in app.css by copying .theme-aurora (dark) or
.theme-crimson (light) and retuning the tokens.
- Verify (see below).
Critical Rules
- Opaque canvas base for light themes.
--chess-square-light is the graph
canvas's solid backdrop. The theme class sits on .app-container, not <body>,
and <body> stays dark (#1B1B1B). A translucent --chess-square-light lets
the dark body bleed through → dark canvas + unreadable labels. Use an opaque
light color (e.g. #FBF7F8), not rgba(..., 0.03). (Guide → Gotcha 1.)
- Graph colors are CSS-driven. Define
--graph-bg, --graph-node-text,
--graph-edge-color, --graph-edge-text, --graph-edge-label-bg in the
block; the graph and designer read them at runtime. No .tsx edits.
- Meet WCAG 2.1 AA contrast. Text and labels need 4.5:1; graph edge lines and
other non-text need 3:1. Set
--on-accent (label color on accent fills) to a
dark value for a light accent (white fails on Aurora's mint) and white
for a dark accent. Edge text must clear 4.5:1 against --graph-edge-label-bg.
Stat-tile icons/values (--stat-blue/green/purple) need 3:1 over the tint and
cascade automatically (bright from :root, dark from .light-theme). Amber
text/icons use --ms-yellow-fg (bright #FFB900 on dark, dark gold #8A6A00
on light); the .progress-fill stops --progress-from/--progress-to each
need 3:1 on the --bg-tertiary track.
npm run test:a11y enforces this for every theme. (Guide → Accessibility.)
- Register dark themes in
DARK_BASED_THEMES so darkMode is correct
(graph fallback, label backplate, PNG export bg).
- Don't introduce brand names in ids, labels, comments, or commits. Use
generic palette names (e.g. Aurora, Crimson, Indigo, Sand).
Person Names
If any example data, docs, or sample instances need person names, use the
name-generator skill — do not invent names.
Validate
npm run dev # switch to the theme in the header; check graph, designer, learn pages
npm run test:a11y # WCAG 2.1 AA contrast for every theme (also a CI gate)
npx tsc --noEmit # the ThemeId union change is type-checked here
npm run build # full build
If npm run build only changed public/learn.json (a timestamp), revert it:
git checkout -- public/learn.json.
Done Criteria
- New swatch + label appear in the picker; selection check mark tracks state.
- Theme persists across reload (
localStorage['theme']).
- Main graph, designer preview, and learn pages are legible in the new theme;
the graph canvas backdrop matches the theme (Gotcha 1 satisfied).
- Dark, Light, Aurora, Crimson unchanged.
npm run test:a11y passes (WCAG 2.1 AA contrast for the new theme).
tsc --noEmit and npm run build pass; no brand references introduced.
1---2name: theme-authoring3description: Add a new color theme to the Ontology Playground. Use when someone wants to create, author, or plug in a theme, palette, color scheme, dark mode, or light mode, or add an entry to the theme picker. Covers the appStore registration plus the CSS token block.4---56# Theme Authoring Skill78## Goal910Plug a new color theme into the Playground so it appears in the header theme11picker, is remembered across sessions, and themes every surface (main graph,12designer preview, learn pages) — with no component or graph-rendering edits.1314## Read First15161. [`docs/theme-authoring-guide.md`](../../../docs/theme-authoring-guide.md) — full architecture, token table, gotchas, worked example.172. [`src/store/appStore.ts`](../../../src/store/appStore.ts) — `ThemeId`, `THEME_OPTIONS`, `DARK_BASED_THEMES`, `isDarkTheme`, `themeClass`.183. [`src/styles/app.css`](../../../src/styles/app.css) — the `:root` / `.light-theme` / `.theme-aurora` / `.theme-crimson` token blocks (copy the nearest one).1920## Intake Questions2122Ask the user:23241. Theme **id** (lowercase, e.g. `indigo`) and **display label** (e.g. `Indigo`)?252. **Dark-based or light-based?** (Determines `DARK_BASED_THEMES` membership and which block to copy.)263. **Accent / signature color** (used for the picker swatch and `--ms-blue*` / `--info`)?274. Any specific surface, text, or graph colors, or should they be derived from the accent?2829## Procedure3031Make all edits in [`src/store/appStore.ts`](../../../src/store/appStore.ts) and32[`src/styles/app.css`](../../../src/styles/app.css). The guide's33"Add a theme in six steps" section has copy-paste snippets.34351. Add the id to the `ThemeId` union.362. Add a `THEME_OPTIONS` entry: `{ id, label, swatch }` (swatch = accent hex).373. If **dark-based**, add the id to `DARK_BASED_THEMES`. If light-based, leave it out.384. Add a `themeClass()` case:39 - dark-based → `return 'theme-<id>';`40 - light-based → `return 'light-theme theme-<id>';` (layer over the light base).415. Add a `.theme-<id>` block in `app.css` by copying `.theme-aurora` (dark) or42 `.theme-crimson` (light) and retuning the tokens.436. Verify (see below).4445## Critical Rules4647- **Opaque canvas base for light themes.** `--chess-square-light` is the graph48 canvas's solid backdrop. The theme class sits on `.app-container`, not `<body>`,49 and `<body>` stays dark (`#1B1B1B`). A translucent `--chess-square-light` lets50 the dark body bleed through → dark canvas + unreadable labels. Use an opaque51 light color (e.g. `#FBF7F8`), not `rgba(..., 0.03)`. (Guide → Gotcha 1.)52- **Graph colors are CSS-driven.** Define `--graph-bg`, `--graph-node-text`,53 `--graph-edge-color`, `--graph-edge-text`, `--graph-edge-label-bg` in the54 block; the graph and designer read them at runtime. No `.tsx` edits.55- **Meet WCAG 2.1 AA contrast.** Text and labels need 4.5:1; graph edge lines and56 other non-text need 3:1. Set `--on-accent` (label color on accent fills) to a57 **dark** value for a **light** accent (white fails on Aurora's mint) and white58 for a dark accent. Edge text must clear 4.5:1 against `--graph-edge-label-bg`.59 Stat-tile icons/values (`--stat-blue/green/purple`) need 3:1 over the tint and60 cascade automatically (bright from `:root`, dark from `.light-theme`). Amber61 text/icons use `--ms-yellow-fg` (bright `#FFB900` on dark, dark gold `#8A6A00`62 on light); the `.progress-fill` stops `--progress-from`/`--progress-to` each63 need 3:1 on the `--bg-tertiary` track.64 `npm run test:a11y` enforces this for every theme. (Guide → Accessibility.)65- **Register dark themes** in `DARK_BASED_THEMES` so `darkMode` is correct66 (graph fallback, label backplate, PNG export bg).67- **Don't introduce brand names** in ids, labels, comments, or commits. Use68 generic palette names (e.g. Aurora, Crimson, Indigo, Sand).6970## Person Names7172If any example data, docs, or sample instances need person names, use the73`name-generator` skill — do not invent names.7475## Validate7677```bash78npm run dev # switch to the theme in the header; check graph, designer, learn pages79npm run test:a11y # WCAG 2.1 AA contrast for every theme (also a CI gate)80npx tsc --noEmit # the ThemeId union change is type-checked here81npm run build # full build82```8384If `npm run build` only changed `public/learn.json` (a timestamp), revert it:85`git checkout -- public/learn.json`.8687## Done Criteria8889- New swatch + label appear in the picker; selection check mark tracks state.90- Theme persists across reload (`localStorage['theme']`).91- Main graph, designer preview, and learn pages are legible in the new theme;92 the graph canvas backdrop matches the theme (Gotcha 1 satisfied).93- Dark, Light, Aurora, Crimson unchanged.94- `npm run test:a11y` passes (WCAG 2.1 AA contrast for the new theme).95- `tsc --noEmit` and `npm run build` pass; no brand references introduced.