@wrksz/themesv0.5.0
API Reference

ThemeProvider

API reference for the ThemeProvider component.

Edit on GitHub

Last updated on

ThemeProvider is a Server Component that wraps your app and injects an inline script to apply the theme before React hydrates, preventing flash of unstyled content.

app/layout.tsx
import { ThemeProvider } from "@wrksz/themes";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en" suppressHydrationWarning>
      <body>
        <ThemeProvider>{children}</ThemeProvider>
      </body>
    </html>
  );
}

ThemeProvider renders an inline <script> and must be used in a Server Component. For nested providers inside Client Components, use ClientThemeProvider instead.

Props

PropTypeDefaultDescription
themesstring[]["light", "dark"]Available themes
defaultThemestring"system"Theme used when no preference is stored
forcedThemestring-Force a specific theme, ignoring user preference
initialThemestring-Server-provided theme that overrides storage on mount. User can still call setTheme to change it
enableSystembooleantrueDetect system preference via prefers-color-scheme
enableColorSchemebooleantrueSet native color-scheme CSS property
attribute"class" | "data-*" | ("class" | "data-*")[]"class"HTML attribute(s) to set on the target element. Must be "class" or a data-* attribute
valueRecord<string, string>-Map theme names to attribute values
targetstring"html"Element to apply theme to ("html", "body", or a CSS selector)
storageKeystring"theme"Key used for storage
storage"localStorage" | "sessionStorage" | "none""localStorage"Where to persist the theme
disableTransitionOnChangebooleanfalseDisable CSS transitions when switching themes
followSystembooleanfalseAlways follow system preference, even after setTheme was called. Also ignores stored value on mount
themeColorstring | Record<string, string>-Update <meta name="theme-color"> on theme change
noncestring-CSP nonce for the inline script
onThemeChange(theme: string) => void-Called whenever the resolved theme changes. Can be an async function or a Server Action

Examples

Custom themes

<ThemeProvider themes={["light", "dark", "high-contrast"]}>
  {children}
</ThemeProvider>

Data attribute instead of class

<ThemeProvider attribute="data-theme">
  {children}
</ThemeProvider>

Multiple classes per theme

Map a theme to multiple CSS classes using a space-separated value:

<ThemeProvider
  themes={["light", "dark", "dim"]}
  value={{ light: "light", dark: "dark high-contrast", dim: "dark dim" }}
>
  {children}
</ThemeProvider>

Force a theme per page

// app/dashboard/layout.tsx
<ThemeProvider forcedTheme="dark">
  {children}
</ThemeProvider>

Server-provided theme

Use initialTheme to initialize from a server-side source (database, session, cookie) on every mount:

// app/layout.tsx (server component)
export default async function RootLayout({ children }) {
  const userTheme = await getUserTheme();

  return (
    <html lang="en" suppressHydrationWarning>
      <body>
        <ThemeProvider
          initialTheme={userTheme ?? undefined}
          onThemeChange={saveUserTheme}
        >
          {children}
        </ThemeProvider>
      </body>
    </html>
  );
}

Disable storage

<ThemeProvider storage="none" defaultTheme="dark">
  {children}
</ThemeProvider>

Meta theme-color

<ThemeProvider themeColor={{ light: "#ffffff", dark: "#0a0a0a" }}>
  {children}
</ThemeProvider>

Works with CSS variables too:

<ThemeProvider themeColor="var(--color-background)">
  {children}
</ThemeProvider>

On this page