better-themes

Advanced Usage

Advanced configuration and usage patterns

Custom Themes

You can define custom themes beyond light and dark:

<ThemeProvider themes={["light", "dark", "purple", "blue", "green"]}>
    {children}
</ThemeProvider>

Use the value prop to map theme names to different attribute values:

<ThemeProvider
    themes={["light", "dark", "purple"]}
    value={{
        light: "light-mode",
        dark: "dark-mode",
        purple: "purple-mode",
    }}
    attribute="data-theme"
>
    {children}
</ThemeProvider>

Multiple Attributes

You can apply themes to multiple attributes simultaneously:

<ThemeProvider attribute={["class", "data-theme"]}>{children}</ThemeProvider>

This is useful when you need both class-based styling (for Tailwind) and data attributes (for custom CSS).

Forced Themes

Force a specific theme for a page or section:

<ThemeProvider forcedTheme="dark">{children}</ThemeProvider>

When forcedTheme is set, it overrides user preferences and localStorage. This is useful for:

  • Landing pages that should always be light
  • Documentation sections that should always be dark
  • A/B testing different themes

Disable System Theme

Disable system theme detection:

<ThemeProvider enableSystem={false} defaultTheme="light">
    {children}
</ThemeProvider>

When enableSystem is false, the "system" option is removed from available themes.

Storage Options

By default, Better Themes uses localStorage to persist theme preferences across all tabs. You can switch to sessionStorage for per-tab theme isolation:

<ThemeProvider storage="sessionStorage">{children}</ThemeProvider>

localStorage vs sessionStorage

Storage TypeBehavior
localStorage (default)Shared across all tabs
sessionStorageIsolated per tab

When to use sessionStorage

Use sessionStorage when you need different themes in different tabs. For example, in a multi-user environment where multiple users are logged into different accounts in separate tabs, each user can have their own theme preference.

Custom Storage Key

Change the key used to store theme preferences:

<ThemeProvider storageKey="my-app-theme">{children}</ThemeProvider>

Useful when you have multiple theme providers in the same app or want to avoid conflicts with other libraries.

Disable Color Scheme

Disable the color-scheme CSS property:

<ThemeProvider enableColorScheme={false}>{children}</ThemeProvider>

The color-scheme property tells browsers which color scheme to use for native UI elements. You might want to disable it if you're handling this manually.

Disable Transitions

Disable CSS transitions when switching themes:

<ThemeProvider disableTransitionOnChange>{children}</ThemeProvider>

This prevents flashy transitions when themes change. Better Themes temporarily disables all transitions, applies the theme, then re-enables them.

Content Security Policy (CSP)

If you're using CSP headers, provide a nonce for the inline script:

<ThemeProvider nonce="your-nonce-here">{children}</ThemeProvider>

The nonce is passed to the inline script that prevents flash on load.

Programmatic Theme Control

Control themes programmatically:

function () {
    const { , , ,  } = ();

    // Set theme directly
    ("dark");

    // Set theme with callback
    (() => ( === "dark" ? "light" : "dark"));

    // Access all available themes
    .(); // ["light", "dark", "system"]

    // Access system preference
    .(); // "dark" or "light"
}

Conditional Rendering

Safely render theme-dependent content:

import { useTheme } from "better-themes";
import { useEffect, useState } from "react";

function ThemedContent() {
    const [mounted, setMounted] = useState(false);
    const { theme } = useTheme();

    useEffect(() => {
        setMounted(true);
    }, []);

    if (!mounted) {
        return <div>Loading...</div>;
    }

    return (
        <div>
            {theme === "dark" && <DarkContent />}
            {theme === "light" && <LightContent />}
        </div>
    );
}

TypeScript

Better Themes is fully typed. Import types for your own components:

import type { ThemeProviderProps, UseThemeProps } from "better-themes";

function CustomProvider(props: ThemeProviderProps) {
    // ...
}

function useCustomTheme(): UseThemeProps {
    // ...
}

On this page