lerpa
ver1.0.0
node20.11
branch⎇ main
uptime14d 03:42:17
cpu3.2%
mem14 MB
teams4,213
utc00:00:00
LIVE
$lerpa --dark

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.

globals.css
/* 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);
}
theme-toggle.tsx
"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.

globals.css
: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.

lerpa · running
turbopack142ms
a11yAAA
tokens14
network14kb