Getting started
Dark mode and motion
Light and dark ship together. One switch for motion; reduced motion always wins.
Dark mode#
Dark values apply under .dark or [data-theme="dark"] on any ancestor, usually <html>. Without React, set the class yourself. With React, ThemeProvider handles light, dark and system, remembers the choice, and follows the OS when set to system.
import { useTheme } from "junco";
const { theme, resolvedTheme, setTheme } = useTheme();
setTheme("system"); // "light" | "dark" | "system"To stop server-rendered pages flashing the wrong theme, add themeScript() (from junco/server) as an inline script in <head>. It reads the saved choice before the first paint. Until it has read it, useTheme().isMounted is false, so toggles can avoid showing a wrong selected state.
The motion switch#
Set data-motion on <html> (or call setMotion). Every Junco duration is multiplied by --motion-scale, so one attribute turns all motion down.
| Value | --motion-scale | What happens |
|---|---|---|
full | 1 | Everything animates at full distance and speed. |
subtle | 0.6 | Shorter and smaller: less travel, quicker fades. |
off | 0 | No movement. Spinners keep turning, slower, because they carry meaning. |
| reduced motion | 0 | The OS setting always wins, even over data-motion="full". |
This spinner never stops, only slows down.
In your own CSS#
Use the duration utilities and they scale for free, or multiply by the variable yourself:
.panel {
transition: transform calc(var(--duration-base) * var(--motion-scale)) var(--ease-enter);
}