theme
Light, dark and system themes with no flash on load, design tokens, and the components you copy into your app.
What it is
@kitr/theme gives your app light, dark and system themes with no flash on load, design tokens as CSS variables, and kitr ui add to copy components into your app.
Runs in the browser and during server rendering. For utility classes on the same tokens, add tailwind.
Install
kitr add themeFirst time? Run npm i -g @kitr/kitr once. Inside a project, the global kitr runs your project's own version.
Adds @kitr/theme, its provider, config/theme.ts, app/styles/tokens.css and <ThemeScript /> in app/document.tsx. Adds react first if missing. Every change.
Quick start
useTheme() returns the current choice and the functions that change it:
// app/components/theme-button.tsx
import { useTheme } from '@kitr/theme'
export function ThemeButton() {
const { resolved, toggle } = useTheme()
return (
<button type="button" onClick={toggle}>
{resolved === 'dark' ? 'Switch to light' : 'Switch to dark'}
</button>
)
}
Click it and the page turns dark: <html> gets data-theme="dark" and every token switches. The choice is saved, so a reload keeps it. kitr ui add theme-toggle gives you a styled one. Next in the guide: Add a dark mode toggle.
Built on
| Built on | Role |
|---|---|
| CSS custom properties | The tokens: colors, radii, spacing, with a dark set under [data-theme="dark"]. |
| shadcn/ui-compatible registries | The component format kitr ui add reads and copies into app/components/ui/. |
| class-variance-authority | Component variants in the copied components. |
kitr adds the provider, the no-flash script, the cookie for server rendering, typed tokens and the component registry.
Problems it solves
- A white flash before dark mode. Avoid a flash on load.
- Light, dark and system as three code paths. Let users pick light, dark or system.
- Colors copied between files. Use the tokens in CSS.
- Rebranding by search and replace. Brand the colors.
- Component libraries that fight the design system. Add components.