Skip to content

Theming

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.

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
<!-- swap to data-theme="light" to force light -->
<html data-theme="dark">
...
</html>

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>

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>

Colors live in two layers — Colors has the catalog, Principles has the reasoning.

Components reference only this layer, so one declaration moves every component that uses the role:

:root {
--color-primary: var(--color-green-600);
}

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);
}

Both layers are plain declarations on :root. Redefine the palette in your own stylesheet to ship a different brand.

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.