Dark mode
Because every component reads CSS variables (see Theming), dark mode is just a different set of token values. Swap the values and the whole UI follows — no per-component logic, no conditional class names.
Two approaches
Pick whichever fits your app. Both set the same variables; they only differ in how the active scheme is selected.
1. Attribute toggle (user choice)
Set a data-theme attribute on <html> and define a token block per scheme. This is the pattern Lerpa UI itself uses, and it lets users pick a theme regardless of their OS setting.
/* default (dark) tokens */
:root {
--bg: oklch(0.10 0.012 285);
--text: oklch(0.95 0.005 300);
}
/* a light preset, applied when data-theme="paper" */
[data-theme="paper"] {
--bg: oklch(0.99 0.003 95);
--text: oklch(0.22 0.01 285);
}"use client";
export function ThemeToggle() {
const toggle = () => {
const el = document.documentElement;
const next = el.dataset.theme === "paper" ? "lime" : "paper";
el.dataset.theme = next;
localStorage.setItem("theme", next);
};
return (
<button type="button" onClick={toggle} aria-label="Toggle theme">
Toggle theme
</button>
);
}To avoid a flash of the wrong theme, read the saved value and set data-theme in a tiny inline script before first paint, and add suppressHydrationWarning to <html> in your root layout.
2. System preference
Prefer to follow the OS automatically? Wrap the alternate tokens in a prefers-color-scheme media query.
:root {
color-scheme: light dark;
/* light defaults */
--bg: oklch(0.99 0.003 95);
--text: oklch(0.22 0.01 285);
}
@media (prefers-color-scheme: dark) {
:root {
--bg: oklch(0.10 0.012 285);
--text: oklch(0.95 0.005 300);
}
}Why this works
- One source of truth. Components reference
var(--bg),var(--text),var(--accent), etc. — never literal colors. - oklch contrast holds. Tokens use
oklch(), so light and dark ladders keep predictable contrast ratios. - Instant. Switching is a single attribute or media change; no re-render of component trees is required.
Want a starting palette for either mode? Generate and export one in the Theme Studio.