Tailwind @theme block + admin theme selector

Tailwind @theme block + admin theme selector

#2 in tonybierman/dx-blog — merged 2026-05-29

Summary

Makes the blog's accent a first-class, themeable token and adds an admin UI to change it live.

@theme block (136af95)

  • Adds a Tailwind v4 @theme block in tailwind.css defining a brand-* accent scale (50–950), built in oklch around a single --brand-hue knob — change one number and every brand-400/500/600 utility shifts hue together. Also exposes a --font-sans typeface token.
  • Re-points all 22 sky-{400,500,600} accent usages (reader.rs, widgets.rs, admin.rs) to brand-*, and recompiles assets/tailwind.css.

Admin theme selector (28b3e05)

  • /admin/settings → Theme: hue preset swatches (Sky/Indigo/Violet/Pink/Crimson/Orange/Emerald/Teal) + a 0–360 slider, each previewing instantly via document.documentElement.style.setProperty('--brand-hue', …) and persisting site-wide.
  • site_settings(key, value) table (idempotent) stores theme_hue.
  • get_theme_hue (public, default 235) + set_theme_hue (gated on SETTINGS_WRITE, clamped 0–360).
  • App root injects :root { --brand-hue: N } after the stylesheets so the stored theme recolors every brand-* utility for all visitors. The compiled-in default covers the pending state, so an un-themed site shows no flash.

Notes

  • Theme changes hue only — per-step lightness/chroma stay fixed so every accent stays legible on the dark background.
  • The --font-sans token lists Inter first but no webfont is loaded, so it falls back to system-ui (unchanged look) until a font <link> is added.

Test plan

  • cargo check --no-default-features --features server,sqlite — server ✓
  • cargo check --no-default-features --features web --target wasm32-unknown-unknown — wasm client ✓
  • cargo test --no-default-features --features server,sqlite — 7 passing ✓
  • assets/tailwind.css recompiled; brand-* + selector utility classes verified present.

🤖 Generated with Claude Code

Last updated 2026-05-30