Skip to content

ThemeProvider

ThemeProvider

Category: Surfaces & shell

<ThemeProvider defaultTheme="light">
<App />
</ThemeProvider>;
// inside any descendant:
const { theme, toggle } = useTheme();
<Button onClick={toggle}>Switch to {theme === 'light' ? 'dark' : 'light'}</Button>;

SSR

When rendering on the server, set data-theme on <html> yourself to avoid a flash. ThemeProvider with rootElement="document" will reconcile after hydration.

Install: @helix-ui/core

import { ThemeProvider, useTheme } from '@helix-ui/core';

status: stable · since: 0.1.0

Tags: theme, light, dark, provider

Anatomy

<ThemeProvider theme="dark">
⟨all components inherit data-theme=dark⟩
</ThemeProvider>

Layout

  • display — block
  • width — auto
  • height — auto
  • intrinsicSize — unstyled wrapper; sets data-theme on root
  • stackable — true
  • fullBleed — false

Visual

A presentational wrapper that toggles data-theme="light" or data-theme="dark" on a wrapping element. All helix-ui tokens are scoped to that attribute.

Props

NameTypeDefaultDescription
theme'light' | 'dark'—Controlled theme.
defaultTheme'light' | 'dark'lightInitial theme when uncontrolled.
rootElement'document' | 'wrapper'documentWhere to apply data-theme. document writes to <html>. wrapper renders a div.
themeColorbooleantrue when rootElement is 'document'Keep <meta name="theme-color"> in step with the theme so the browser chrome is tinted to match — the Android address bar, the Safari tab bar, an installed PWA’s title bar. Off by default for a wrapper-scoped provider, which has no business writing to <head>.
platform'auto' | 'web' | 'ios' | 'macos' | 'android' | 'windows'—Which platform’s conventions the whole document renders under, written to data-helix-ui-platform on <html>. An app that themes through HelixUIDNAProvider gets this from its DNA; an app that only flips data-theme has nowhere else to say it. Omit it entirely and the attribute is left alone.
onChange(theme: Theme) => void—Theme change handler.

Slots

  • children — your app

Tokens used

color.text.primary, color.bg.surface.default

Accessibility

Notes

  • Theme switch should respect prefers-color-scheme on first load — wire that into your defaultTheme.
  • Avoid mounting two ThemeProviders with different themes; tokens cascade by attribute.

Composes with

ComponentRelationNote
HelixUIDNAProviderchildDNA tunes the genome inside a chosen theme.

Prompt examples

These are the AI prompt → JSX mappings used by the helix-ui prompt DSL and integrations like Cursor / Claude Code.

toggle dark mode

“wrap the app for theme switching”

<ThemeProvider theme={theme}>
<App />
</ThemeProvider>