ComponentsTheming
ThemeProvider
Light, dark and system themes plus the global motion switch.
Light, dark and system themes plus the global motion switch.
The same component at all four levels. Pick the one that fits your project; they share tokens, so they mix.
npm i junco @junco/tailwindimport { ThemeProvider, useTheme, themeScript } from "junco";
// app/layout.tsx
<html lang="en" suppressHydrationWarning>
<head>
<script dangerouslySetInnerHTML={{ __html: themeScript() }} />
</head>
<body>
<ThemeProvider>{children}</ThemeProvider>
</body>
</html>
// anywhere
const { theme, setTheme, resolvedTheme, motion, setMotion } = useTheme();These controls drive this whole site. The state below comes from useTheme().
ThemeProvider#defaultThemedefaultMotiontheme / motiononThemeChange / onMotionChangestorageKey| Prop | Type | Default |
|---|---|---|
defaultThemeUsed until the user picks one. | "light" | "dark" | "system" | "system" |
defaultMotionprefers-reduced-motion always turns motion off regardless. | "full" | "subtle" | "off" | "full" |
theme / motionControlled mode. The provider then never writes storage. | Theme / Motion | – |
onThemeChange / onMotionChangeCalled when setTheme / setMotion runs. | (value) => void | – |
storageKeylocalStorage prefix: stores <key>-theme and <key>-motion. | string | "junco" |
useTheme()#themeresolvedThemesetTheme / setMotionmotion| Prop | Type | Default |
|---|---|---|
themeWhat the user picked. | "light" | "dark" | "system" | – |
resolvedThemeWhat's showing now. | "light" | "dark" | – |
setTheme / setMotionChange and persist. | (value) => void | – |
motionThe global motion level. | "full" | "subtle" | "off" | – |
themeScript()#An inline script for <head> that applies the saved theme before first paint.
options| Prop | Type | Default |
|---|---|---|
optionsMatch what you pass to ThemeProvider. | { defaultTheme?, defaultMotion?, storageKey? } | – |