Theming
Airframe uses tokens as CSS variables. Override them directly in CSS—no build step required.
Theme Studio
Section titled “Theme Studio”Need to map an existing design system? Use Theme Studio to upload Tokens Studio / DTCG / CSS / Figma Variables, preview on real patterns, lint unknown tokens, and export theme.css.
CLI equivalent (via @airframeui/build):
npx af theme generate --from ./tokens.json -o theme.css
npx af theme lint theme.cssAI / MCP: install @airframeui/mcp and use generate_theme → lint_theme. See @airframeui/theme/rules and Build Tool.
Color Tokens
Section titled “Color Tokens”Override Primitives (Simplest)
Section titled “Override Primitives (Simplest)”Override hex primitives (--af-base-*) in :root for simple, global brand color changes. This is the easiest approach and changes everything that uses that color:
:root {
--af-base-primary: #018183;
--af-base-secondary: #6b7280;
--af-base-success: #10b981;
--af-base-danger: #ef4444;
--af-base-warning: #f59e0b;
--af-base-info: #3b82f6;
}When to use: Simple brand color swaps, global changes, when you want the same color across all themes.
Limitation: Primitives are shared across all themes, so you can’t have different colors for light/dark/high-contrast.
Override Semantic Tokens (Theme-Specific)
Section titled “Override Semantic Tokens (Theme-Specific)”Override semantic tokens (--af-color-*) with theme suffixes (--dark, --hc-light, --hc-dark) for per-theme control:
:root {
/* Different primary color per theme */
--af-color-primary--dark: #38bdf8; /* Lighter blue in dark mode */
--af-color-action--hc-light: #0066cc; /* Stronger blue for high contrast */
}When to use: Different colors per theme, accessibility adjustments (like stronger colors for high-contrast), fine-grained control.
See: Dark Mode and High Contrast sections for complete examples.
Interaction States
Section titled “Interaction States”Interaction states and soft/hard variants are derived via color-mix():
:root {
--af-hover-mix: 12%;
--af-active-mix: 18%;
--af-soft-mix: 12%;
--af-hard-mix: 45%; /* Dark enough for AA text on soft intent surfaces */
}Badges, chips, and KPI deltas use *-hard text on *-soft backgrounds. Keep --af-hard-mix high enough that success/warning/info hard text clears 4.5:1 on soft.
Dark Mode
Section titled “Dark Mode”Airframe ships with dark tokens and follows system preference by default.
Default Behavior
Section titled “Default Behavior”When you import the core CSS, dark mode follows prefers-color-scheme automatically. No extra configuration is required.
Force a Theme
Section titled “Force a Theme”Dark mode follows system preference by default. To override the system preference, set dark mode on the root element using one of these methods:
data-themeattribute: Standard data attribute.darkclass: CSS class
<!-- Force dark mode using data-theme -->
<html data-theme="dark">
<body>
...
</body>
</html>
<!-- Force dark mode using .dark class -->
<html class="dark">
<body>
...
</body>
</html>
<!-- Force light mode -->
<html data-theme="light">
<body>
...
</body>
</html>Custom Dark Mode Colors
Section titled “Custom Dark Mode Colors”Override dark mode colors using the --dark suffix pattern on semantic tokens (--af-color-*). This works regardless of how dark mode is applied (media query, class, or data attribute):
:root {
/* Override dark mode colors - works with any dark mode implementation */
/* Base surfaces */
--af-color-background--dark: #0a0a0a;
--af-color-surface-primary--dark: #0a0a0a;
/* Text */
--af-color-text--dark: #ffffff;
/* Borders */
--af-color-border--dark: #333333;
/* Intent (primary) */
--af-color-primary--dark: #38bdf8;
}Note: You can also override primitives (--af-base-primary) for a global change, but semantic tokens with --dark suffix give you theme-specific control. See Color Tokens for when to use each approach.
High Contrast
Section titled “High Contrast”Accessibility is foundational to Airframe. High-contrast themes ensure your UI is accessible to users with low vision, color blindness, or who need higher contrast for readability.
High-contrast tokens are applied automatically when a user enables high contrast in their OS settings. If both dark mode and high contrast are enabled, the high-contrast dark tokens apply.
Customizing High Contrast Colors
Section titled “Customizing High Contrast Colors”Airframe detects the system prefers-contrast: more or prefers-contrast: high preference and automatically applies high-contrast semantic tokens. Override these tokens to customize colors while maintaining accessibility.
Override high contrast colors using the --hc-light and --hc-dark suffix patterns on semantic tokens (--af-color-*). You can also override primitives (--af-base-primary--hc-light / --af-base-primary--hc-dark) for brand color changes that apply across all semantic tokens.
:root {
/* High contrast light mode - override semantic tokens */
--af-color-background--hc-light: #ffffff;
--af-color-surface-primary--hc-light: #ffffff;
--af-color-text--hc-light: #000000;
--af-color-text-muted--hc-light: #333333;
--af-color-border--hc-light: #000000;
--af-color-border-strong--hc-light: #000000;
/_ Override action/primary colors for high contrast _/
--af-color-action--hc-light: #0066cc; /_ Stronger blue for better contrast _/
--af-color-on-action--hc-light: #ffffff;
/_ High contrast dark mode - override semantic tokens _/
--af-color-background--hc-dark: #000000;
--af-color-surface-primary--hc-dark: #1a1a1a;
--af-color-text--hc-dark: #ffffff;
--af-color-text-muted--hc-dark: #cccccc;
--af-color-border--hc-dark: #ffffff;
--af-color-border-strong--hc-dark: #ffffff;
/_ Override action/primary colors for high contrast dark _/
--af-color-action--hc-dark: #60a5fa; /_ Lighter blue for dark backgrounds _/
--af-color-on-action--hc-dark: #000000;
}Important: Always verify contrast ratios meet WCAG 2.2 AA requirements (4.5:1 for normal text, 3:1 for large text and UI components). Use a contrast checker before deploying.
Available High Contrast Override Tokens
Section titled “Available High Contrast Override Tokens”| Token | HC Light (--hc-light) | HC Dark (--hc-dark) |
|---|---|---|
| Surface | ||
| background | --af-color-background--hc-light | --af-color-background--hc-dark |
| surface-primary | --af-color-surface-primary--hc-light | --af-color-surface-primary--hc-dark |
| surface-secondary | --af-color-surface-secondary--hc-light | --af-color-surface-secondary--hc-dark |
| surface-tertiary | --af-color-surface-tertiary--hc-light | --af-color-surface-tertiary--hc-dark |
| Text | ||
| text | --af-color-text--hc-light | --af-color-text--hc-dark |
| text-muted | --af-color-text-muted--hc-light | --af-color-text-muted--hc-dark |
| text-inverse | --af-color-text-inverse--hc-light | --af-color-text-inverse--hc-dark |
| Border | ||
| border | --af-color-border--hc-light | --af-color-border--hc-dark |
| border-strong | --af-color-border-strong--hc-light | --af-color-border-strong--hc-dark |
| Action / primary | ||
| action | --af-color-action--hc-light | --af-color-action--hc-dark |
| on-action | --af-color-on-action--hc-light | --af-color-on-action--hc-dark |
| Intent (on-) | ||
| on-primary | --af-color-on-primary--hc-light | --af-color-on-primary--hc-dark |
| on-secondary | --af-color-on-secondary--hc-light | --af-color-on-secondary--hc-dark |
| on-success | --af-color-on-success--hc-light | --af-color-on-success--hc-dark |
| on-warning | --af-color-on-warning--hc-light | --af-color-on-warning--hc-dark |
| on-danger | --af-color-on-danger--hc-light | --af-color-on-danger--hc-dark |
| on-info | --af-color-on-info--hc-light | --af-color-on-info--hc-dark |
Testing High Contrast
Section titled “Testing High Contrast”Enable high contrast in your OS (Windows: Settings → Ease of Access → High contrast) or use browser DevTools to simulate prefers-contrast: more. Verify all text meets WCAG 2.2 AA (4.5:1 for normal text, 3:1 for large text) and test in both light and dark modes.
Typography Tokens
Section titled “Typography Tokens”Typography is driven by semantic tokens so brands can override safely:
Font Families
Section titled “Font Families”:root {
/* Override semantic font tokens */
--af-font-primary: 'Inter', 'Roboto', sans-serif;
--af-font-heading: 'Playfair Display', serif;
--af-font-body: var(--af-font-primary);
--af-font-code: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
}Type Scale
Section titled “Type Scale”:root {
/* Override type scale, leading (line-height), and weights */
--af-text-lg: 1.125rem;
--af-leading-normal: 1.5;
--af-weight-medium: 500;
}Component Tokens
Section titled “Component Tokens”Component tokens provide override-friendly sizing for buttons, inputs, and other controls:
:root {
/* Shared control tokens */
--af-control-min-height: 3rem;
--af-control-radius: var(--af-radius-md);
/_ Choice controls (checkbox, radio, switch track) _/
--af-choice-size: 1.5rem;
--af-switch-height: var(--af-choice-size);
--af-switch-width-ratio: 0.8;
/_ Button-specific _/
--af-btn-gap: 0.75rem;
--af-btn-padding-x: var(--af-space-4);
/_ Input-specific _/
--af-input-placeholder-color: rgba(0, 0, 0, 0.45);
}Motion Tokens
Section titled “Motion Tokens”Motion tokens provide consistent timing for transitions and animations, with automatic reduced motion support:
:root {
/* Duration */
--af-duration-fast: 120ms;
--af-duration-md: 200ms;
/_ Easing _/
--af-ease-standard: cubic-bezier(.2, .0, .2, 1);
--af-ease-emphasized: cubic-bezier(.2, .0, 0, 1);
}Complete Example
Section titled “Complete Example”:root {
/* Colors */
--af-base-primary: #0ea5e9; /* Global brand color */
--af-hover-mix: 12%;
--af-hard-mix: 45%; /* Hard text on soft surfaces (AA) */
/* Override dark mode colors */
--af-color-background--dark: #0a0a0a;
--af-color-primary--dark: #38bdf8; /* Different primary in dark mode */
/_ Typography _/
--af-font-heading: ui-sans-serif, system-ui, sans-serif;
--af-text-lg: 1.1875rem;
/_ Components _/
--af-control-min-height: 2.5rem;
--af-choice-size: 1.375rem;
--af-btn-radius: var(--af-radius-lg);
}Next Steps
Section titled “Next Steps”- Tokens Reference - Complete token documentation
- Advanced Overrides - Deep customization