Getting Started
Install and configure @wrksz/themes in your Next.js app.
These docs cover 2.x. Install @wrksz/themes without a prerelease tag. See Upgrading from 1.x.
Try it
A nested ClientThemeProvider scoped to this card with storage="none", so it never touches the page theme. Two of the themes are custom.
theme …resolved …
Ada Lovelace
Commented on Reader view
The sepia palette reads well at night. Could we ship it as the default for the reader view?
"use client";
import { ClientThemeProvider, useTheme } from "@wrksz/themes/client";
const themes = ["light", "dark", "sepia", "forest"] as const;
export function ThemePreview({ children }: { children: React.ReactNode }) {
return (
<ClientThemeProvider
themes={themes}
defaultTheme="system"
attribute="data-theme"
target="#preview"
storage="none"
>
<Picker />
<div id="preview">{children}</div>
</ClientThemeProvider>
);
}
function Picker() {
const { theme, setTheme } = useTheme<(typeof themes)[number]>();
return [...themes, "system" as const].map((name) => (
<button key={name} aria-pressed={theme === name} onClick={() => setTheme(name)}>
{name}
</button>
));
}#preview { --bg: #fcfcfc; --fg: #1f1f1f; --accent: #1f1f1f; }
#preview[data-theme="dark"] { --bg: #141414; --fg: #f2f2f2; --accent: #f2f2f2; }
#preview[data-theme="sepia"] { --bg: #f4ecd8; --fg: #433422; --accent: #8a5a2b; }
#preview[data-theme="forest"] { --bg: #1d2620; --fg: #e3ead9; --accent: #9cc797; }
#preview {
background: var(--bg);
color: var(--fg);
}Installation
pnpm add @wrksz/themesSetup
Add ThemeProvider to your root layout. Import from @wrksz/themes/next for Next.js - this avoids the React 19 inline script warning by using useServerInsertedHTML. Add suppressHydrationWarning to <html> to prevent hydration mismatches.
import { ThemeProvider } from "@wrksz/themes/next";
export default function RootLayout({ children }: { children: React.ReactNode }) {
return (
<html lang="en" suppressHydrationWarning>
<body>
<ThemeProvider>{children}</ThemeProvider>
</body>
</html>
);
}Usage
Use the useTheme hook in any Client Component to read and update the current theme.
"use client";
import { useTheme } from "@wrksz/themes/client";
export function ThemeToggle() {
const { resolvedTheme, setTheme } = useTheme();
return (
<button
type="button"
onClick={() => setTheme(resolvedTheme === "dark" ? "light" : "dark")}
>
Toggle theme
</button>
);
}Import paths
ThemeProvider in Next.js (recommended)useTheme, useThemeValue, useThemeEffect, ThemedImage, ClientThemeProvider, createThemesuseTheme importuseThemeValue importuseThemeEffect importThemedImage importClientThemeProvider importcreateThemes importcreateThemes with NextThemeProvider and ThemeScriptThemeProvider with systemThemeMap and same-document syncClientThemeProvider with themeRoot, systemThemeMap, and same-document syncThemeProvider alias and createThemes for framework-neutral React usageThe API is identical to next-themes. Migrating requires changing one import line: @wrksz/themes/next instead of next-themes. See Why not next-themes? for a full comparison.
Requirements
- Next.js 16+
- React 18+ (uses native
useEffectEventon React 19.2+) - TypeScript 5.9+ Breakingv2.0.0 (
typescriptpeer is>=5.9from2.0.0; 4.x and 5.0–5.8 are unsupported on this line)
Next steps
- ThemeProvider API - all available props
- useTheme API - hook reference
- Examples - Tailwind, scoped theming, Shadow DOM, and more