Theme switcher
JavaScripttheme.js Requires _defaults.js
Theme control is provided by theme.js. There are two kinds of control: a switcher
(toggles light ⇄ dark) and setters (pick an explicit theme, including system).
Both are wired automatically from data-* attributes.
<div class="flex flex-wrap items-center gap-6"> <!-- Simple toggle: flips between light and dark on click --> <button type="button" class="button-secondary" data-theme-switcher>Toggle theme</button>
<!-- Explicit setters: each button sets one theme; the active one gets [data-active] --> <div class="inline-flex gap-1 rounded-xl border border-border p-1"> <button type="button" class="button-ghost-foreground data-active:button-tertiary" data-theme-set="system">System</button> <button type="button" class="button-ghost-foreground data-active:button-tertiary" data-theme-set="light">Light</button> <button type="button" class="button-ghost-foreground data-active:button-tertiary" data-theme-set="dark">Dark</button> </div></div>
<p class="mt-4 text-foreground-subtle"> The surface follows the current theme — <span class="font-medium text-foreground-primary">background</span> and <span class="font-medium text-foreground">text</span> tokens repaint automatically.</p>Markup
Section titled “Markup”<!-- toggles between light and dark --><button type="button" data-theme-switcher>Toggle theme</button>
<!-- explicit setters; the active one receives [data-active] --><button type="button" data-theme-set="system">System</button><button type="button" data-theme-set="light">Light</button><button type="button" data-theme-set="dark">Dark</button>Attributes
Section titled “Attributes”| Attribute | On | Meaning |
|---|---|---|
data-theme-switcher |
any clickable | Clicking flips light ⇄ dark. |
data-theme-set="system|light|dark" |
any clickable | Clicking sets that exact theme. |
data-active |
a setter | [auto-set] — present on the setter whose theme is active. Style with data-active:…. |
data-theme-switcher-created |
a switcher | [auto-set] [internal] — idempotency guard. |
data-theme-set-created |
a setter | [auto-set] [internal] — idempotency guard. |
Functions (global)
Section titled “Functions (global)”| Function | Signature | Purpose |
|---|---|---|
setTheme(theme) |
'system' | 'light' | 'dark' → void |
Apply a theme, persist it, update [data-active] on setters. |
getTheme() |
→ { theme, current } |
theme is the saved choice; current is the resolved light/dark. |
createThemeSwitchers() |
→ void | Wire any new [data-theme-switcher] elements. |
createThemeSetters() |
→ void | Wire any new [data-theme-set] elements. |
Dependencies
Section titled “Dependencies”_defaults.js— the theme is stored underwindow._storage.theme(the keytheme). Loadingtheme.jswithout_defaults.jswill fail.- The pre-paint head script — applies the saved theme to
<html>before first paint so there’s no flash. It reads the samelocalStoragekey. Keep it in the head; see Vanilla setup.
How it applies
Section titled “How it applies”setTheme toggles the light / dark class on <html>. All
semantic and action tokens carry dark-mode values, so a single
class change repaints the whole UI. Transitions are momentarily disabled during the swap
to avoid a color-animation flash.