@absoluteui/theme
Theme runtime, built-in themes, tokens, component tokens, contrast evaluation, and web fonts.
import { ... } from '@absoluteui/theme';How to use
Section titled “How to use”This package holds the design tokens, the built-in themes (absolute-default, absolute-dark, absolute-high-contrast, and absolute-system), the theme runtime that applies them, and the WCAG contrast engine. Reach for it once at startup, and again when you override tokens or check your own colors. The Theming guide explains tokens, overrides, and custom themes in depth; to build a theme from brand colors, use the Theme Designer engine.
How do I switch the theme, density, or direction at runtime?
Section titled “How do I switch the theme, density, or direction at runtime?”Start the runtime once, then change configuration: the runtime keeps <html> in sync. Pass applyDirection: true if it should also set dir.
import { configureAbsoluteUI } from '@absoluteui/core';import { startThemeRuntime } from '@absoluteui/theme';
const stop = startThemeRuntime({ applyDirection: true });configureAbsoluteUI({ common: { theme: 'absolute-dark', density: 'compact', direction: 'rtl' } });const html = document.documentElement;[html.dataset.auiTheme, html.dataset.auiDensity, html.dir]; // => ['absolute-dark', 'compact', 'rtl']stop(); // stops syncing; the attributes stayHow do I follow the operating system’s dark mode?
Section titled “How do I follow the operating system’s dark mode?”Use absolute-system: its CSS follows prefers-color-scheme and prefers-contrast without any script. A family exported from the Theme Designer has the same <name>-system theme in its theme.css.
import { configureAbsoluteUI } from '@absoluteui/core';import { startThemeRuntime } from '@absoluteui/theme';
startThemeRuntime();configureAbsoluteUI({ common: { theme: 'absolute-system' } });document.documentElement.dataset.auiTheme; // => 'absolute-system'How do I read or override a token?
Section titled “How do I read or override a token?”Every token is a --aui-* custom property. The built-in definitions give you the values in script; set the property on :root or on any container (in CSS or inline) to override it for that subtree.
import { absoluteDefault } from '@absoluteui/theme';
absoluteDefault.tokens['color-primary']; // => '#1E40AF'const panel = document.createElement('section');document.body.append(panel);panel.style.setProperty('--aui-radius-md', '0.75rem');getComputedStyle(panel).getPropertyValue('--aui-radius-md'); // => '0.75rem'How do I override a component token?
Section titled “How do I override a component token?”Component tokens such as --aui-button-radius fall back to a global token until you set them. Set one on a container, or put it in a registered theme so it follows theme switches.
import { absoluteDefault, applyTheme, getComponentToken, registerTheme } from '@absoluteui/theme';
getComponentToken('button-radius')?.fallback; // => 'radius-md'registerTheme({ ...absoluteDefault, name: 'acme-hr', tokens: { ...absoluteDefault.tokens, 'button-radius': '999px' } });applyTheme('acme-hr');getComputedStyle(document.documentElement).getPropertyValue('--aui-button-radius'); // => '999px'Registered themes are applied as constructable stylesheets, so they work under a strict Content Security Policy.
How do I check the contrast of my own color pair?
Section titled “How do I check the contrast of my own color pair?”contrastRatio measures two parsed colors; compare it with WCAG_AA_MINIMUM and ask suggestForeground for the nearest passing color. evaluateThemeContrast runs the same check over every pair a theme declares.
import { WCAG_AA_MINIMUM, absoluteDefault, contrastRatio, evaluateThemeContrast, parseColor, suggestForeground } from '@absoluteui/theme';
const text = parseColor('#94A3B8');const card = parseColor('#FFFFFF');const ratio = text && card ? contrastRatio(text, card) : 0; // => ≈ 2.56ratio >= WCAG_AA_MINIMUM.text; // => falseconst fixed = text && card ? suggestForeground(text, card, WCAG_AA_MINIMUM.text) : null; // => '#6C7786'const report = evaluateThemeContrast({ ...absoluteDefault, name: 'acme', tokens: { ...absoluteDefault.tokens, 'color-text-muted': '#94A3B8' } });report.failed.length; // => 4How do I load the web font?
Section titled “How do I load the web font?”The default font stack starts with Noto Sans but never downloads it. Opt in by importing the loader stylesheet, and allow the Google Fonts hosts in your Content Security Policy. A hosted font service receives every visitor’s IP address, so self-hosting with @font-face is often the better choice.
import '@absoluteui/theme/fonts/noto-sans.css';import { webFontHosts } from '@absoluteui/theme';
const csp = `style-src 'self' ${webFontHosts.google.styleSrc}; font-src 'self' ${webFontHosts.google.fontSrc}`;What goes wrong?
Section titled “What goes wrong?”Theme names must be built in or registered, built-in names are reserved, and token values are checked against a safe CSS grammar (no url(), braces, or semicolons), so imported themes cannot inject CSS. The runtime needs a DOM: start it in browser code, not during server rendering.
import { absoluteDefault, applyTheme, registerTheme } from '@absoluteui/theme';
applyTheme('acme-hr'); // => throws THEME_UNKNOWNregisterTheme({ ...absoluteDefault }); // => throws THEME_RESERVED_NAMEregisterTheme({ ...absoluteDefault, name: 'acme-hr', tokens: { ...absoluteDefault.tokens, 'color-bg': 'url(/x.png)' } }); // => throws THEME_INVALIDAPI reference
Section titled “API reference”Component tokens
Section titled “Component tokens”Functions
Section titled “Functions”componentTokensToScss
SCSS map $aui-component-tokens: (component: (property: fallback)) for aui.ctoken().
function componentTokensToScss(): string;getComponentToken
Look up a component token by its flat name.
function getComponentToken(name: string): (ComponentTokenSpec & { readonly component: string; readonly property: string;}) | undefined;Constants
Section titled “Constants”componentTokenNames
Flat component token names (button-radius), in registry order.
const componentTokenNames: readonly string[];componentTokens
const componentTokens: Readonly<Record<string, ComponentTokenGroup>>;Interfaces
Section titled “Interfaces”ComponentTokenGroup
interface ComponentTokenGroup { readonly tokens: Readonly<Record<string, ComponentTokenSpec>>; readonly contrastPairs: readonly ContrastPair[];}ComponentTokenSpec
interface ComponentTokenSpec { readonly fallback: string; readonly kind: ComponentTokenKind; readonly usage: string;}ComponentTokenKind
type ComponentTokenKind = 'color' | 'dimension' | 'shadow' | 'font-weight';Contrast
Section titled “Contrast”Functions
Section titled “Functions”composite
Source-over alpha compositing of top onto an opaque bottom.
function composite(top: RGBA, bottom: RGBA): RGBA;contrastRatio
function contrastRatio(a: RGBA, b: RGBA): number;evaluateThemeContrast
Evaluate every declared contrast pair of a theme.
function evaluateThemeContrast(theme: ThemeDefinition): ContrastReport;parseColor
function parseColor(value: string): RGBA | null;relativeLuminance
function relativeLuminance(c: RGBA): number;suggestForeground
Nearest foreground (mixed toward black or white) that meets required against bg.
function suggestForeground(fg: RGBA, bg: RGBA, required: number): string | null;Constants
Section titled “Constants”WCAG_AA_MINIMUM
WCAG 2.2 AA minimums: 1.4.3 (text), 1.4.3 large text, 1.4.11 (non-text).
const WCAG_AA_MINIMUM: Readonly<Record<ContrastKind, number>>;Interfaces
Section titled “Interfaces”ContrastReport
interface ContrastReport { readonly theme: string; readonly passed: readonly ContrastResult[]; readonly failed: readonly ContrastResult[]; readonly errors: readonly string[];}ContrastResult
interface ContrastResult { readonly rule: 'WCAG 2.2 1.4.3' | 'WCAG 2.2 1.4.11'; readonly pair: ContrastPair; readonly ratio: number; readonly required: number; readonly pass: boolean; readonly severity: Severity; readonly remediation: string | null;}RGBA
interface RGBA { r: number; g: number; b: number; a: number;}Severity
axe-core impact levels; contrast results use critical and serious, designer advisories add the others.
type Severity = 'critical' | 'serious' | 'moderate' | 'minor';Optional tokens
Section titled “Optional tokens”Functions
Section titled “Functions”optionalTokenProblem
Why a value is not allowed for an optional token, or null when it is.
function optionalTokenProblem(name: string, value: string): string | null;Constants
Section titled “Constants”optionalTokenNames
const optionalTokenNames: readonly string[];optionalTokens
const optionalTokens: Readonly<Record<string, OptionalTokenSpec>>;Interfaces
Section titled “Interfaces”OptionalTokenSpec
interface OptionalTokenSpec { readonly kind: OptionalTokenKind; readonly usage: string; readonly values?: readonly string[];}OptionalTokenKind
Optional global tokens (the specification “scrollbar appearance where standards allow”).
Unlike role tokens they are not required for theme completeness and have no default:
while unset, the declarations that read them are invalid at computed-value time and
the user agent’s native appearance applies. Uses the standard CSS Scrollbars Styling
properties scrollbar-color and scrollbar-width.
type OptionalTokenKind = 'color' | 'keyword';Runtime
Section titled “Runtime”Functions
Section titled “Functions”applyTheme
Apply a theme by name to a target element (default: the document element).
function applyTheme(name: string, options?: ApplyThemeOptions): void;getTheme
function getTheme(name: string): ThemeDefinition | undefined;registerTheme
Register a custom theme (validated, the specification). Returns the normalized definition.
function registerTheme(input: unknown): ThemeDefinition;startThemeRuntime
Keep the target in sync with global configuration (theme, density, optional direction). Returns a disposer.
function startThemeRuntime(options?: Omit<ApplyThemeOptions, 'density'>): Disposer;Constants
Section titled “Constants”builtInThemeNames
Built-in theme names accepted by the theme configuration option.
const builtInThemeNames: readonly ["absolute-default", "absolute-dark", "absolute-high-contrast", "absolute-system"];Interfaces
Section titled “Interfaces”ApplyThemeOptions
interface ApplyThemeOptions { target?: HTMLElement; density?: 'compact' | 'comfortable' | 'spacious'; applyDirection?: boolean;}Serialize
Section titled “Serialize”Functions
Section titled “Functions”isSafeTokenValue
function isSafeTokenValue(value: unknown): value is string;themeToCssText
Theme as CSS text scoped to a selector, inside the aui.theme cascade layer.
function themeToCssText(theme: ThemeDefinition, selector?: string): string;tokensToDeclarations
CSS declarations for a token map (custom properties prefixed --aui-).
function tokensToDeclarations(tokens: Readonly<Record<string, string>>): string;tokensToJson
Design-token JSON.
function tokensToJson(themeList: readonly ThemeDefinition[]): string;tokensToScss
SCSS maps for all given themes plus densities.
function tokensToScss(themeList: readonly ThemeDefinition[]): string;validateTheme
Validate an untrusted theme (e.g. imported JSON) against schema version 1.
function validateTheme(input: unknown): ThemeDefinition;Tokens
Section titled “Tokens”Constants
Section titled “Constants”absoluteDark
const absoluteDark: ThemeDefinition;absoluteDefault
const absoluteDefault: ThemeDefinition;absoluteHighContrast
const absoluteHighContrast: ThemeDefinition;densities
Density overrides applied over the comfortable baseline.
const densities: Readonly<Record<'compact' | 'spacious', TokenMap>>;requiredTokenNames
Every theme must define exactly these tokens (the specification theme completeness).
const requiredTokenNames: readonly string[];themes
const themes: { readonly 'absolute-default': ThemeDefinition; readonly 'absolute-dark': ThemeDefinition; readonly 'absolute-high-contrast': ThemeDefinition;};Interfaces
Section titled “Interfaces”ContrastPair
interface ContrastPair { readonly foreground: string; readonly background: string; readonly backdrop?: string; readonly kind: ContrastKind; readonly usage: string;}ThemeDefinition
interface ThemeDefinition { readonly schemaVersion: 1; readonly name: string; readonly mode: ThemeMode; readonly seeds: TokenMap; readonly tokens: TokenMap; readonly contrastPairs: readonly ContrastPair[];}ContrastKind
type ContrastKind = 'text' | 'large-text' | 'non-text';ThemeMode
Built-in themes. Seeds are brand hues and are never consumed by components directly; components use role tokens only. This module is the single source of truth: SCSS maps, CSS custom properties, tokens.json, and the contrast gate are all generated from it.
type ThemeMode = 'light' | 'dark' | 'high-contrast';TokenMap
type TokenMap = Readonly<Record<string, string>>;Web fonts
Section titled “Web fonts”Functions
Section titled “Functions”webFontProblem
Why a web font entry is invalid, or null when it is valid.
function webFontProblem(font: unknown): string | null;webFontProviderOf
Provider implied by a stylesheet URL.
function webFontProviderOf(stylesheet: string): WebFontProvider;webFontsToCss
@import rules for the given fonts (valid only at the top of a stylesheet).
function webFontsToCss(fonts: readonly WebFont[]): string;Constants
Section titled “Constants”defaultWebFonts
The default theme family’s web fonts.
const defaultWebFonts: readonly WebFont[];notoSansStylesheet
Google Fonts CSS for Noto Sans: italic, width 62.5-100, weight 100-900.
const notoSansStylesheet = "https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wdth,wght@0,62.5..100,100..900;1,62.5..100,100..900&display=swap";webFontHosts
Hosts each provider serves from, for Content-Security-Policy style-src and font-src.
const webFontHosts: Readonly<Record<Exclude<WebFontProvider, 'custom'>, { readonly styleSrc: string; readonly fontSrc: string;}>>;Interfaces
Section titled “Interfaces”WebFont
interface WebFont { readonly provider: WebFontProvider; readonly family: string; readonly stylesheet: string;}WebFontProvider
Web fonts (the specification typography and font stacks). A theme lists the font
stylesheets it needs; the font stack tokens name the families. Loading is always
opt-in: absolute-default.css never requests a third-party font. The default theme’s
font-family-sans starts with “Noto Sans”, and @absoluteui/theme/fonts/noto-sans.css
loads it from Google Fonts for applications that choose to.
Privacy and CSP: a hosted font service receives every visitor’s IP address and user
agent. Applications must allow its hosts in style-src and font-src, and decide on
consent where that applies (for example the GDPR); self-hosting avoids both.
type WebFontProvider = 'google' | 'bunny' | 'custom';