API reference

ThemeProvider

stable
function ThemeProvider({ themes, active, children }: ThemeProviderProps): JSX.Element
themesreadonly Theme[]required

All themes that might be active at this scope. Their CSS-variable definitions are emitted once via a <style> element so theme switches become attribute swaps rather than React re-renders. Include any pre-generated combination themes (e.g. dark_red) used by nested <Theme> boundaries.

activestringrequired

Name of the active theme. Must match the name of one of the entries in themes; otherwise CSS variables fall back to browser defaults.

childrenReactNode

Subtree that consumes the active theme.

Updated 3 days agoEdit on GitHubWeb & native

Description

Top-level theme provider. Renders a <style> element containing every theme's tokens, scoped to [data-theme="<name>"], and wraps its children in a <div data-theme={active}>.

A theme switch is a single attribute write — set active to a different name and the cascade flips. No React re-renders, no unmount/remount.

Theme boundary

Theme

stable
function Theme({ name, children }: ThemeProps): JSX.Element
namestringrequired

Theme name to apply to this subtree. Combined with the parent chain, motif looks up a registered combination theme (e.g. dark_red), falling back to the inner name (red) or the parent active name when no combination is registered.

childrenReactNode

Subtree that switches to the new active theme.

Sub-tree theme boundary. Switches the active theme for descendants by setting data-theme on a wrapping element. The CSS-variable cascade handles the visual change; React state is not involved.

When nested inside a parent <Theme> (or <ThemeProvider>), motif composes the names with _ and looks for a registered combination theme. Pre-generate the combinations you care about and pass them all to <ThemeProvider themes={...}> — they activate automatically when the chain matches.

Example

example.tsx
import { ThemeProvider, Theme, Box } from 'usemotif';
import { lightTheme, darkTheme, lightRed, darkRed } from './theme';
 
<ThemeProvider themes={[lightTheme, darkTheme, lightRed, darkRed]} active="light">
<Box bg="$colors.surface.base">{/* light */}</Box>
 
<Theme name="dark">
  <Box bg="$colors.surface.base">{/* dark */}</Box>
 
  <Theme name="red">
    <Box bg="$colors.surface.base">{/* dark_red, if registered */}</Box>
  </Theme>
</Theme>
</ThemeProvider>;