Files
skills/docs/ui/react/react-ui/src/theme/use-theme/use-theme.md
2026-05-29 08:20:56 +01:00

2.9 KiB

useTheme() — read the active theme registry

(no submodules)

Purpose

The primary read-side hook for the chassis theme system. Returns the active theme, the registered theme list, the setTheme callback, the React-transition isPending flag, and the live reducedMotionActive boolean. Throws ReactUiError(REACT_UI.NO_PROVIDER) outside of a <ThemeProvider> so misuses fail fast rather than silently render an unthemed UI.

Features

  • Returns a ThemeContextValue snapshot — every field is required
  • Throws when called outside a Provider so consumer code surfaces the misuse at the call site rather than silently degrading
  • Pairs cleanly with useTheme().setTheme(name) for an awaitable transition; consumers can await setTheme('dark') and inspect getComputedStyle(document.documentElement) immediately after

Usage: Basic example

import { useTheme } from "@suaveplan/react-ui/theme/use-theme";

function CurrentThemeBadge() {
    const { theme } = useTheme();
    return <span data-theme-name={theme.name}>{theme.name}</span>;
}

Usage: Advanced example

import { useTheme } from "@suaveplan/react-ui/theme/use-theme";

function ThemeButtons() {
    const { themes, theme, setTheme, isPending } = useTheme();
    return (
        <div role="group" aria-busy={isPending}>
            {themes.map((t) => (
                <button
                    key={t.name}
                    type="button"
                    onClick={() => {
                        void setTheme(t.name);
                    }}
                    aria-pressed={t.name === theme.name}
                >
                    {t.name}
                </button>
            ))}
        </div>
    );
}

API Reference

  • useTheme(): ThemeContextValue
    • theme: ThemePlugin — currently active theme
    • themes: readonly ThemePlugin[] — every theme registered with the surrounding <ThemeProvider>
    • setTheme: (name: string) => Promise<void> — async because the chassis wraps the transition in useTransition; await resolves after the React commit but <html data-theme> mutation runs in the following effect cycle
    • isPending: boolean — true while a setTheme transition is in flight
    • reducedMotionActive: boolean — live prefers-reduced-motion flag resolved by the Provider
  • Throws ReactUiError(REACT_UI.NO_PROVIDER) on missing Provider.

Implementation notes

The hook is a thin useContext reader; the heavy lifting lives in <ThemeProvider>. Keeping it slim means it can be called freely in any component without added rerender cost — a setTheme invocation re-emits the context value (because theme and isPending change), which causes every reader to re-render once. Components that should only re-render on TOKEN changes (not theme name changes) read useThemeTokens() instead of pulling theme.cssVariables from useTheme().