Theming
All colors, radii, shadows and sizes are CSS custom properties (design tokens). Dark mode, high contrast, font scaling, brand colors, multiple tenants and white-labelling are built in, and every component follows them automatically.
Dark / light / auto
auto (default) follows the operating system. The choice is saved per browser (disable with persist: false).
Orion.theme.setMode('dark'); // 'light' | 'dark' | 'auto'
Orion.theme.toggle(); // light ⇄ dark
Orion.theme.cycle(); // light → dark → auto
Orion.theme.resolved; // 'light' | 'dark' (what is displayed)
Orion.on('theme', e => console.log(e.mode, e.resolved));
Set the initial mode without JavaScript flashes with <html data-theme="dark"> or <script src="orion.js" data-theme="dark">.
Scoped themes
Add .o-theme-dark or .o-theme-light to any element to theme only that area, for example a dark sidebar on a light page. Floating panels opened from inside it inherit the scope.
Dark scope
Tokens are redefined for this subtree.
Light scope
Always light, even in dark mode.
Brand colors at runtime
Orion.theme.set() changes tokens live. Readable text colors (--o-on-*) and hover shades are derived automatically.
Multi-tenant & white-label
Register named themes (tokens, branding, default mode) and switch between them. Elements marked with data-o-brand="name" / data-o-brand="logo" are updated automatically, as are the favicon and title.
Orion.theme.register('acme', {
primary: '#e11d48', radius: '4px', font: 'Inter, sans-serif', mode: 'light',
brand: { name: 'ACME Corp', logo: '/acme.svg', logoDark: '/acme-white.svg', favicon: '/acme.ico', title: 'ACME Admin' }
});
Orion.theme.use('acme'); // persisted; Orion.theme.reset() to clear
High contrast & font size
High contrast strengthens borders, muted text and focus rings (it also follows prefers-contrast: more). The font scale resizes every rem-based size.
Orion.theme.setContrast(true);
Orion.theme.setFontScale(1.125); // 0.75 – 1.5
Design tokens
Override tokens in your CSS (:root { --o-primary: … }) or with Orion.theme.set(). Semantic colors have derived variants: -hover, -subtle, -border, -text and --o-on-*.
| Token group | Variables |
|---|---|
| Brand & semantic | --o-primary secondary success danger warning info light dark + --o-on-*, -hover, -subtle, -border, -text |
| Surfaces & text | --o-bg --o-surface --o-surface-2 --o-surface-3 --o-elevated --o-border --o-border-strong --o-text --o-text-muted --o-text-subtle --o-backdrop |
| Typography | --o-font-sans --o-font-mono --o-font-scale --o-fs-xs … --o-fs-4xl --o-lh |
| Shape | --o-radius-xs --o-radius-sm --o-radius --o-radius-lg --o-radius-xl --o-radius-pill, --o-shadow-xs … --o-shadow-xl |
| Controls | --o-control-h --o-control-h-sm --o-control-h-lg --o-control-px --o-input-bg --o-input-border --o-ring-width --o-ring-alpha --o-focus |
| Layout | --o-sidebar-w --o-sidebar-w-mini --o-header-h --o-sidebar-bg --o-sidebar-text --o-header-bg --o-container-max |
| Motion & stacking | --o-ease --o-dur-fast --o-dur --o-dur-slow, --o-z-dropdown … --o-z-tooltip |
| Data visualisation | --o-chart-1 … --o-chart-8 (validated categorical order), --o-seq-100 … 700, --o-div-neg/mid/pos, --o-status-good/warning/serious/critical |
| Color context | .o-c-{color} sets --o-c --o-on-c --o-c-subtle --o-c-text --o-c-border, which many components accept (avatars, progress, stat icons, timeline markers). |
API
| Member | Description |
|---|---|
| theme.mode / resolved | Current mode (light|dark|auto) and the displayed mode. |
| theme.setMode(m) / toggle() / cycle() | Change the mode (persisted). |
| theme.set(tokens, scopeEl?) | Apply tokens (primary, radius, font… or raw --o-* names). |
| theme.get(token) | Computed token value. |
| theme.reset() | Remove runtime tokens and the active tenant. |
| theme.register(name, def) / use(name) | Multi-tenant themes (tokens + brand + mode). |
| theme.brand({ name, logo, logoDark, favicon, title }) | White-label branding. |
| theme.setContrast(bool) / setFontScale(n) | Accessibility preferences (persisted). |
| theme.exportCSS() | CSS snippet of the runtime overrides. |
| Orion.color.* | parse toHex toRgb toHsl fromHsl mix lighten darken alpha luminance contrast readable palette random |
| data-o-action="theme" | data-o-value: light dark auto toggle cycle contrast font+ font- font0 or a tenant name. |
| Events | Orion.on('theme', fn), DOM event o-theme on document, Orion.on('brand', fn). |