Theming
System accent
Section titled “System accent”One variable drives the navbar stripe, the footer stripe, and <BrandTile>. Set it at :root:
:root { --color-system-accent: var(--color-purple-600);}Defaults to a neutral gray. Three derived tokens track it through color-mix:
| Token | What it controls | Derivation |
|---|---|---|
--color-system-accent |
Navbar + footer stripe, .brand-tile bg |
The value you set |
--color-system-accent-hover |
Reserved for hover states | 12% mix toward --color-text |
--color-system-accent-muted |
Reserved for subtle backgrounds | 12% accent over --color-surface |
--color-system-accent-content |
Tile / icon foreground | light-dark(paper, black) |
Bright accents like --color-yellow-400 need a manual -content override:
:root { --color-system-accent: var(--color-yellow-400); --color-system-accent-content: var(--color-black);}In React, <AdminRoot systemAccent="…"> sets it inline on one subtree. To run several accents in one app, see App shell › Branding.
Dark mode
Section titled “Dark mode”Mode resolves from CSS color-scheme, which also flips native form controls, scrollbars, and the page background before paint:
| Selector | color-scheme |
When it wins |
|---|---|---|
:root |
light dark |
default — follows the OS |
[data-theme="light"] |
light |
forces light |
[data-theme="dark"] |
dark |
forces dark |
Force a mode
Section titled “Force a mode”<!-- swap to data-theme="light" to force light --><html data-theme="dark"> ...</html>Scope to a subtree
Section titled “Scope to a subtree”The selector isn’t tied to :root, so any element flips its own subtree. An embedded <AdminRoot> then owns its color-scheme outright and the host page’s does not leak in.
<section data-theme="dark"> <!-- everything inside renders in dark mode --></section><AdminRoot theme="dark">{/* ... */}</AdminRoot>Tailwind dark: variant
Section titled “Tailwind dark: variant”Fires under prefers-color-scheme: dark or inside [data-theme="dark"], and is suppressed inside [data-theme="light"]:
<div class="shadow-md dark:shadow-xl">...</div>Override tokens
Section titled “Override tokens”Colors live in two layers — Colors has the catalog, Principles has the reasoning.
A semantic role
Section titled “A semantic role”Components reference only this layer, so one declaration moves every component that uses the role:
:root { --color-primary: var(--color-green-600);}A palette tone
Section titled “A palette tone”Replaces a Flexoki tone everywhere it is used, including inside any semantic role pointing at it:
:root { --color-blue-600: oklch(0.55 0.18 250);}The whole palette
Section titled “The whole palette”Both layers are plain declarations on :root. Redefine the palette in your own stylesheet to ship a different brand.
Popup layering
Section titled “Popup layering”Portaled popups — <Select> and <Tooltip> — render on .popup-layer, whose z-index reads --z-popup and defaults to 1000. Lower it when an <AdminRoot> sits inside a host page with chrome that should still paint above admin popups:
.my-embedded-panel { --z-popup: 106;}Declare it on the admin root or any ancestor — the default is a var() fallback rather than a token, so any declaration wins outright.
<Dialog> and <Drawer> are native <dialog> elements in the top layer and ignore z-index; popups opened inside one are portaled into the dialog so they stay above its backdrop.