Light and dark via data-theme on <html> — override
semantic aliases, not primitives.
Dark is the default. Set data-theme="dark" or
data-theme="light" on the document element. Semantic tokens under
html[data-theme="light"] remap purpose aliases; primitive scales stay
unchanged.
Use the theme toggle in the corner of this page to preview light and dark live —
the same data-theme attribute your app should set.
<html lang="en" data-theme="dark">
<!-- or data-theme="light" -->
</html>
Static multipage sites ship with a default data-theme in HTML. Restoring
theme only after deferred JS runs paints dark first. Skeletons and spinners do not fix
that. Put a tiny blocking script in <head> that sets
data-theme synchronously. This docs site uses
data-ca-theme-boot: it restores theme only after a consent choice, reading
optional localStorage (Accept) or tab-only sessionStorage (Accept or Essential). See
Cookies.
useTheme, setTheme, getTheme,
toggleTheme, and toggleThemeFromEvent live on
caustica-design/core. They read and write
document.documentElement’s data-theme.
import { setTheme, useTheme, toggleThemeFromEvent } from 'caustica-design/core'
function ThemeToggle() {
const [theme] = useTheme()
return (
<button type="button" onClick={toggleThemeFromEvent}>
{theme === 'dark' ? 'Light' : 'Dark'}
</button>
)
}
// Imperative (no animation)
setTheme('light', { immediate: true })
// Circular reveal from a point
setTheme('dark', { origin: { x: 24, y: 24 } })
Toggling theme runs a circular reveal from the control via the View Transitions API
when available. CSS lives in motion.css:
html[data-theme-to] + --theme-x /
--theme-y / --theme-r drive
vt-theme-reveal
.is-theme-leaving /
.is-theme-entering on the shell
.is-theme-toggling on the toggle buttonprefers-reduced-motion: reduce skips animationTry the theme toggle in the corner — same circular reveal as examples and Zonely.
Theme tokens ship with both CSS entries. Pick the surface your host needs:
caustica-design/css/foundation — fonts, token layers, and body chrome (no
component classes)
caustica-design/css — foundation plus buttons, panels, pickers, and the rest
Importing only token files without foundation/base drops body font, canvas glow, and grain. For brand remaps, see Tokens → override.
Wrap the host UI in .ca-root. Prefer fewer stacked
backdrop-filter layers; dense screens can lower
--ca-blur-glass / --glass-blur.
import 'caustica-design/css/foundation'
// or full system:
import 'caustica-design/css'