FoundationsTheme
next-themes provider, toggle, and selector integrated with preferences.
The theme package wraps next-themes and syncs the active theme into the preferences storage key via applyThemePreference (no extra DOM writes).
When to use it
| Export | Use when |
|---|---|
ThemeProvider | App root — replaces raw next-themes provider |
ThemeToggle | Icon button cycling light/dark |
ThemeSelector | Light / dark / system dropdown |
ThemePreferenceSync | Advanced: mount inside a custom provider |
Installation
Registry CLI
Requires a one-time components.json registry entry for @feature-kit/theme.
pnpm dlx shadcn@latest add https://feature-kits.vercel.app/r/theme.jsonNamespaced: npx shadcn@latest add @feature-kit/theme
Manual installation
Monorepo consumers can depend on workspace:* packages instead of the registry CLI.
pnpm add theme preferences uiDependencies
// apps/your-app/package.json
"dependencies": {
"theme": "workspace:*"
"preferences": "workspace:*"
"ui": "workspace:*"
}Transpile (Next.js)
// next.config.ts
transpilePackages: ["theme", "preferences", "ui"]Import
import { ThemeProvider, ThemeToggle, ThemeSelector } from "@/lib/feature-kit/theme"Usage
Replace the raw ThemeProvider from next-themes with the kit provider (already wired in the playground Providers):
import { ThemeProvider } from "theme"
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
{children}
</ThemeProvider>Theme controls
`ThemeProvider` syncs with `preferences` via `applyThemePreference` on change.
Card surface
Muted surface
Secondary surface
ThemePreferenceSync runs automatically when syncPreferences is true (default). It mirrors light, dark, and system into the same localStorage key used by preferences bootstrap.
Related
- Providers
- Layout dashboard shell — header actions slot for
ThemeSelector
Live preview with sample data in the docs. Theme controls preview