ThemeProvider
ThemeProvider owns the document's color preference. Put one at the application root, then decide
whether people choose light, dark or system; a nested provider still writes to the same document.
Examples
A saved preference
A control should set an explicit choice, not invert an unknown state. This preview uses its own
storageKey, so trying it cannot replace the documentation site's saved preference.
Following the operating system
system is the default. It resolves to a concrete light or dark theme and follows an operating
system change, while preserving system as the reader's stored choice.
When to use
Use ThemeProvider once at an application root when color mode is a durable preference. Set the same
storageKey in the blocking first-paint script and in the provider, or the page can flash one theme
before React applies another.
Reach for something else when:
- The product has no user-selectable color mode — set
data-themein the document shell and do not add a preference control. - The visual identity, rather than the color mode, changes per tenant — use the White-label guide
and pass
brandfrom the tenant configuration.
Accessibility
- ThemeProvider emits no landmark, role or ARIA attribute. It sets
data-themeon<html>and, when provided,data-brand. - A color-mode control is consumer UI: use a native Button or another named control, and keep it in normal tab order.
- Changing a theme does not move focus. Do not replace the focused control while applying the new preference.
- Never make color the only signal for a selected mode; expose the current choice in the control's text or state.
Props
| Name | Type | Required | Description |
|---|---|---|---|
defaultTheme | Theme | — | Theme to use when nothing is stored yet. Default: `"system"`. |
storageKey | string | — | localStorage key holding the choice. Default: `"lyra-theme"`. |
brand | string | — | Sets `data-brand` on `<html>` for white-label theming. See the white-label guide. |
children | ReactNode | Required |
Plain HTML
ThemeProvider is React behavior, but the resulting document attribute is plain HTML. The same stylesheet classes then resolve against the selected token set:
<html data-theme="dark">
<body>
<button class="lyra-btn lyra-btn--primary lyra-btn--md" type="button">Save changes</button>
</body>
</html>