Skip to main content
Batoi UIF Docs

Tokens and Theming

Use explicit Batoi UIF tokens to control interface color, typography, density, radius, and theme exports.

Version 3.0.0 Version 3 active maintenance Reviewed Aug 11, 2026 Next review Nov 11, 2026

Owner: Batoi Engineering Reviewed by: Batoi UIF Maintainers Source revision: b2f3478

Browse Batoi UIF Documentation Tokens and Theming

Tokens and Theming

Batoi UIF themes should be driven by explicit tokens instead of one-off visual overrides.

The Theme Builder example demonstrates how a client-side tool can adjust tokens and export application-ready CSS.

Token Pipeline

Controls color radius density CSS Tokens variables and JSON Preview + Export theme.css theme.json

Core Tokens

TokenPurpose
--uif-brandPrimary brand/action color
--uif-accentSupporting accent color
--uif-neutralMain text and structural color
--uif-surfacePrimary surface color
--uif-radiusControl and card radius
--uif-densitySpacing density
--uif-fontFont stack

UIF 2.2.0 also provides semantic typography weights, line heights, tracking, readable content measures, responsive title sizes, and text utilities. The default stack uses system fallbacks and does not require a webfont download.

Use helpers such as uif-page-title, uif-section-title, uif-component-title, uif-label, uif-caption, and uif-prose to preserve hierarchy. Size, weight, line-height, alignment, muted-text, and semantic-color utilities are available for smaller adjustments.

Example CSS

:root {
  --uif-brand: #0f70b7;
  --uif-accent: #00a999;
  --uif-neutral: #1e293b;
  --uif-surface: #ffffff;
  --uif-radius: 8px;
  --uif-density: 1rem;
  --uif-font: Inter, Arial, sans-serif;
}

Guidance

  • Keep token names stable.
  • Avoid per-page color overrides where tokens are enough.
  • Preview themes against forms, cards, tables, and primary actions.
  • Export CSS and JSON when a theme needs to move between applications.

Implement Light and Dark Modes

Define both modes with the same semantic token names. Components should consume surface, text, border, brand, and status tokens without testing the current mode themselves.

:root,
[data-theme="light"] {
  color-scheme: light;
  --uif-surface: #ffffff;
  --uif-surface-elevated: #f8fafc;
  --uif-text: #1e293b;
  --uif-text-muted: #64748b;
  --uif-border: #cbd5e1;
}

[data-theme="dark"] {
  color-scheme: dark;
  --uif-surface: #101a2a;
  --uif-surface-elevated: #172235;
  --uif-text: #f1f5f9;
  --uif-text-muted: #b6c2d1;
  --uif-border: #3b4a60;
}

Use an explicit user choice when one exists and otherwise follow the operating-system preference. Persist only the mode name, not a complete token payload.

const root = document.documentElement;
const stored = localStorage.getItem('theme');
const preferred = matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';

function applyTheme(theme) {
  const next = theme === 'dark' ? 'dark' : 'light';
  root.dataset.theme = next;
  root.style.colorScheme = next;
}

applyTheme(stored || preferred);

document.querySelector('[data-theme-toggle]')?.addEventListener('click', () => {
  const next = root.dataset.theme === 'dark' ? 'light' : 'dark';
  localStorage.setItem('theme', next);
  applyTheme(next);
});

Place the initial mode script in the document head when possible so the correct surface is applied before first paint. A toggle must have an accessible name and expose its current state. Verify text, links, focus indicators, controls, disabled states, alerts, tables, charts, images, and code blocks in both modes. Do not invert photographs or logos with a blanket CSS filter.

The UIF 2.3.0 examples follow this pattern: the selected mode is persisted, applied before the example renders, and paired with the appropriate light or dark UIF logo asset.