Getting Started: Install, usage, tokens, theming, layouts, and framework setup — best first read for coding agents. # Introduction > Airframe — a structural UI system designed for humans and AI **Airframe** is a structural UI system designed for humans and AI. Import one CSS file. Get layout primitives (`af-stack`, `af-inline`, `af-grid`), a full token layer, accessible patterns, and a readable DOM. No build step. No JavaScript runtime. No framework lock-in. Like an aircraft airframe, it defines the form and integrity of the system. You bring the engine: React, Vue, Angular, AI-generated code, or whatever comes next. ## Structure first [Section titled “Structure first”](#structure-first) Most tools help you style surfaces or assemble components. Airframe starts with the layout contract underneath — stack, inline, grid, tokens, and patterns that keep markup readable. ``` Tailwind → styling utilities Bootstrap → components Airframe → UI structure ``` That is not a brand-new category. It is a different priority: structure before decoration, so the DOM stays understandable when humans or AI change it. ## What it is / isn’t [Section titled “What it is / isn’t”](#what-it-is--isnt) | Airframe is | Airframe is not | | ------------------------------------------------------------------------------- | --------------------------------------- | | Structural primitives and patterns | A component library with JS widgets | | CSS tokens you override at runtime (optional Theme Studio / `af theme` codegen) | A required build step to use the system | | Readable `af-*` markup | Utility soup | | Framework-agnostic CSS | Another React (or Vue) dependency | You keep your framework. Airframe gives the structure that survives it. ## Why start [Section titled “Why start”](#why-start) Readable markup for your team. Predictable patterns for AI. Branding via CSS variables, not a rebuild. Accessibility as infrastructure, not a plugin. [Install Airframe](/docs/installation) · [Read the Manifesto](/docs/manifesto) ## Next Steps [Section titled “Next Steps”](#next-steps) * [Installation](/docs/installation) — get the CSS in your project * [Usage](/docs/usage) — first patterns and primitives * [Layouts](/docs/layouts) — stack, inline, grid, and more * [Tokens & Theming](/docs/theming) — brand it with `--af-*` variables * [Demo](/demo) — an admin UI built only with Airframe classes * [AI Rules](/docs/ai-rules) — the contract for humans and coding agents # Installation > How to install and set up Airframe Install `@airframeui/core`, import one CSS file, and start using patterns. No build plugin required. ## Installation [Section titled “Installation”](#installation) ### 01 — Install the package [Section titled “01 — Install the package”](#01--install-the-package) ``` npm install @airframeui/core # or yarn add @airframeui/core pnpm add @airframeui/core ``` ### 02 — Import the CSS [Section titled “02 — Import the CSS”](#02--import-the-css) Add Airframe to your global stylesheet (recommended): ``` @import "@airframeui/core/core.css"; ``` Or link it from HTML: ``` ``` ### 03 — Start using Airframe [Section titled “03 — Start using Airframe”](#03--start-using-airframe) Use semantic pattern classes immediately: ```

Card Title

Card content goes here.

``` ## Framework guides [Section titled “Framework guides”](#framework-guides) Prefer a framework-specific entrypoint? Use these and skip the generic steps above. ### Next.js [Section titled “Next.js”](#nextjs) Add to `app/globals.css` or `styles/globals.css`: ``` @import "@airframeui/core/core.css"; ``` See the full [Next.js guide](/docs/nextjs). ### React (Vite / Next.js) [Section titled “React (Vite / Next.js)”](#react-vite--nextjs) Add to your main CSS file (e.g. `src/index.css`): ``` @import "@airframeui/core/core.css"; ``` ### Angular [Section titled “Angular”](#angular) Add to `angular.json` under `projects..architect.build.options`: ``` "styles": [ "node_modules/@airframeui/core/core.css", "src/styles.scss" ] ``` Or import in `src/styles.scss`: ``` @import "@airframeui/core/core.css"; ``` See the full [Angular guide](/docs/angular). ### Vue [Section titled “Vue”](#vue) Add to your main CSS file or import from `main.js` / `main.ts`: ``` @import "@airframeui/core/core.css"; ``` ## Next steps [Section titled “Next steps”](#next-steps) * [Usage](/docs/usage) — first patterns and primitives * [Core concepts](/docs/layouts) — layouts, responsive suffix, theming * [Framework Support](/docs/framework-support) — setup overview by framework * [Browser Support](/docs/browser-support) — supported browsers and polyfills # Usage > How to use Airframe in your projects Start using semantic classes immediately after installation. ## Basic Example [Section titled “Basic Example”](#basic-example) ```

Card Title

Card content goes here.

Primary action
``` ### Live Example [Section titled “Live Example”](#live-example) ## Card Title Card content goes here. [Primary action](url) ## Semantic HTML [Section titled “Semantic HTML”](#semantic-html) Airframe styles semantic HTML by default. Many elements work without classes: ```

Main Heading

Section Heading

``` ### Live Example [Section titled “Live Example”](#live-example-1) # Main Heading ## Section Heading EmailSubmit ## Layout Recipes [Section titled “Layout Recipes”](#layout-recipes) Use layout recipes for common patterns: ```

Title

Content

``` ### Live Example [Section titled “Live Example”](#live-example-2) # Title Content Action SaveCancel ## Patterns [Section titled “Patterns”](#patterns) Use pattern classes for common UI structures: ```

Card Title

Card content
Success message
``` ### Live Example [Section titled “Live Example”](#live-example-3) ### Card Title Card content Success message Name ## Responsive Design [Section titled “Responsive Design”](#responsive-design) Use responsive suffixes for breakpoint-specific styles: ```
Item 1
Item 2
Item 3
``` ### Live Example [Section titled “Live Example”](#live-example-4) Item 1 Item 2 Item 3 *Resize your browser to see the grid adapt: 1 column on mobile, 2 on tablet, 3 on desktop.* ## Utilities [Section titled “Utilities”](#utilities) Use utility classes for spacing, typography, and more: ```
Content

Centered muted text

Hidden on small screens
``` ### Live Example [Section titled “Live Example”](#live-example-5) Content with padding and margin Centered muted text Hidden on small screens, visible on medium and up ## Next Steps [Section titled “Next Steps”](#next-steps) * [Layouts](/docs/layouts) - Learn layout patterns * [Theming](/docs/theming) - Customize colors and tokens * Browse [Patterns](/docs/patterns) for more UI structures # Tokens Override **hex primitives** in `:root`: ``` :root { --af-base-primary: #018183; } ``` Interaction is derived via `color-mix()`: ``` :root { --af-hover-mix: 12%; --af-active-mix: 18%; } ``` For dark mode and theme overrides, see [Theming](/docs/theming#dark-mode). ## Color Palette [Section titled “Color Palette”](#color-palette) Airframe ships with a calm, modern default palette designed for product UI. Neutrals form the structure—they provide the foundation for surfaces, borders, and text. Accent colors indicate motion and intent—they signal actions, states, and meaning. Everything is overridable. Override primitives in `:root` to change the entire system, or adjust semantic tokens for targeted changes. ### Color Primitives [Section titled “Color Primitives”](#color-primitives) ``` :root { /* Accent colors */ --af-base-primary: #4663f5; --af-base-secondary: #22d3ee; --af-base-tertiary: #111827; --af-base-success: #22c55e; --af-base-warning: #fbbf24; --af-base-danger: #dc2626; --af-base-info: #38bdf8; /_ Neutrals _/ --af-base-white: #ffffff; --af-base-black: #000000; --af-base-neutral-50: #f8fafc; --af-base-neutral-100: #f1f5f9; --af-base-neutral-200: #e2e8f0; --af-base-neutral-300: #cbd5e1; --af-base-neutral-400: #94a3b8; --af-base-neutral-500: #64748b; --af-base-neutral-600: #475569; --af-base-neutral-700: #334155; --af-base-neutral-800: #1f2937; --af-base-neutral-900: #111827; } ``` ### Global Color Mix Knobs [Section titled “Global Color Mix Knobs”](#global-color-mix-knobs) These control how interaction states are derived via `color-mix()`: ``` :root { --af-hover-mix: 12%; /* Hover state color mix */ --af-active-mix: 18%; /* Active state color mix */ --af-soft-mix: 12%; /* Soft variant color mix (lighter) */ --af-hard-mix: 45%; /* Hard variant color mix (darker; AA text on soft) */ --af-border-mix: 22%; /* Border color mix */ } ``` Soft intent surfaces (`*-soft`) pair with hard text (`*-hard`) in badges, chips, and KPI deltas so small text meets WCAG AA (4.5:1). Mid-tone intent colors (`--af-color-success`, etc.) stay vivid for fills and icons — do not use them as small text on soft tints. ### Action color (theme-overridable) [Section titled “Action color (theme-overridable)”](#action-color-theme-overridable) The **action** token (`--af-color-action`) is the semantic “main CTA/brand color” used for buttons, links, focus rings, and other interactive elements. It defaults to primary; **`--af-color-primary`** (and `--af-color-on-primary`) are resolved from action, so all existing components that use primary automatically respect the override. Override action per theme when you want a different accent in dark or high-contrast modes. **For high-contrast themes, ensure colors meet WCAG 2.2 AA contrast requirements** (4.5:1 for normal text, 3:1 for large text): ``` /* Dark mode */ @media (prefers-color-scheme: dark) { :root { --af-color-action--dark: #60a5fa; --af-color-on-action--dark: #0f172a; } } /_ Or when using a manual dark theme class _/ [data-theme="dark"], .dark { --af-color-action--dark: #60a5fa; --af-color-on-action--dark: #0f172a; } /_ High-contrast light - use stronger colors for better contrast _/ :root { --af-color-action--hc-light: #0066cc; /_ Stronger blue meets WCAG AA _/ --af-color-on-action--hc-light: #ffffff; } /_ High-contrast dark - lighter colors for dark backgrounds _/ :root { --af-color-action--hc-dark: #60a5fa; /_ Lighter blue for dark mode _/ --af-color-on-action--hc-dark: #000000; } ``` **Note:** High-contrast overrides work automatically with system `prefers-contrast: more` or `prefers-contrast: high` preference. No media queries needed—just define the `--hc-light` and `--hc-dark` tokens in `:root`. See [High Contrast Theming](/docs/theming#high-contrast) for complete examples. Derived tokens (`--af-color-action-hover`, `-action-active`, `-action-soft`, `-action-hard`) are computed from the resolved action via `color-mix()`, so they stay consistent when you override. ## Typography Tokens [Section titled “Typography Tokens”](#typography-tokens) Typography is driven by semantic tokens so brands can override safely: ### Font Families [Section titled “Font Families”](#font-families) ``` :root { /* Font primitives */ --af-base-font-sans: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, "Apple Color Emoji", "Segoe UI Emoji"; --af-base-font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; /_ Semantic font tokens _/ --af-font-primary: var(--af-base-font-sans); /_ Primary font (used for body text by default) _/ --af-font-heading: var(--af-font-primary); /_ Heading font (applied to h1-h6, .af-text-h_, .af-text-display) _/ --af-font-body: var(--af-base-font-sans); /_ Body text font _/ --af-font-code: var(--af-base-font-mono); /_ Code font _/ --af-font-mono: var(--af-base-font-mono); /_ Monospace font */ } ``` **Customizing fonts:** ``` :root { /* Use custom web fonts */ --af-font-primary: 'Inter', 'Roboto', sans-serif; --af-font-heading: 'Playfair Display', serif; /* Different font for headings */ --af-font-body: var(--af-font-primary); /* Body uses primary */ } ``` ### Type Scale [Section titled “Type Scale”](#type-scale) ``` :root { /* Core type scale */ --af-text-xs: 0.75rem; --af-text-sm: 0.875rem; --af-text-md: 1rem; --af-text-lg: 1.125rem; --af-text-xl: 1.25rem; --af-text-2xl: 1.5rem; --af-text-3xl: 1.875rem; /_ Leading (line-height) - typography term for vertical spacing between lines _/ /_ Use --af-leading-_ tokens; these map to CSS line-height property */ --af-leading-tight: 1.1; --af-leading-normal: 1.5; --af-leading-loose: 1.7; /_ Weights _/ --af-weight-regular: 400; --af-weight-medium: 500; --af-weight-semibold: 600; --af-weight-bold: 700; --af-weight-extrabold: 800; } ``` ### Role Tokens (Override-Friendly) [Section titled “Role Tokens (Override-Friendly)”](#role-tokens-override-friendly) Typography role tokens map semantic roles (h1, h2, body, etc.) to type scale values. Override these to customize typography without touching primitives: ``` :root { /* Display type */ --af-type-display-size: var(--af-text-3xl); --af-type-display-weight: var(--af-weight-bold); --af-type-display-leading: var(--af-leading-tight); /_ Heading sizes _/ --af-type-h1-size: var(--af-text-3xl); --af-type-h2-size: var(--af-text-2xl); --af-type-h3-size: var(--af-text-xl); --af-type-h4-size: var(--af-text-lg); --af-type-h5-size: var(--af-text-md); --af-type-h6-size: var(--af-text-sm); /_ Heading weights _/ --af-type-h1-weight: var(--af-weight-semibold); --af-type-h2-weight: var(--af-weight-semibold); --af-type-h3-weight: var(--af-weight-semibold); --af-type-h4-weight: var(--af-weight-semibold); --af-type-h5-weight: var(--af-weight-semibold); --af-type-h6-weight: var(--af-weight-semibold); /_ Heading leading _/ --af-type-h1-leading: var(--af-leading-tight); --af-type-h2-leading: var(--af-leading-tight); --af-type-h3-leading: var(--af-leading-tight); --af-type-h4-leading: var(--af-leading-normal); --af-type-h5-leading: var(--af-leading-normal); --af-type-h6-leading: var(--af-leading-normal); /_ Heading letter spacing _/ --af-type-h1-tracking: -0.02em; --af-type-h2-tracking: -0.01em; --af-type-h3-tracking: 0em; --af-type-h4-tracking: 0em; --af-type-h5-tracking: 0em; --af-type-h6-tracking: 0em; /_ Body and caption _/ --af-type-body-size: var(--af-text-md); --af-type-body-weight: var(--af-weight-regular); --af-type-body-leading: var(--af-leading-normal); --af-type-caption-size: var(--af-text-sm); --af-type-caption-weight: var(--af-weight-regular); --af-type-caption-leading: var(--af-leading-normal); /_ Semantic typography roles _/ --af-text-body-size: var(--af-text-md); --af-text-body-leading: var(--af-leading-normal); --af-text-heading-leading: var(--af-leading-tight); --af-text-heading-weight: var(--af-weight-semibold); } ``` ## Spacing Tokens [Section titled “Spacing Tokens”](#spacing-tokens) The space scale provides consistent spacing values used throughout the system: ``` :root { --af-space-0: 0px; --af-space-1: 4px; --af-space-2: 8px; --af-space-3: 12px; --af-space-4: 16px; --af-space-5: 24px; --af-space-6: 32px; --af-space-7: 40px; --af-space-8: 48px; } ``` These tokens are used by spacing utilities (`af-p-*`, `af-m-*`, `af-gap-*`) and layout recipes. ## Border Radius Tokens [Section titled “Border Radius Tokens”](#border-radius-tokens) Radius tokens control the roundness of corners: ``` :root { --af-radius-0: 0px; --af-radius-sm: 6px; --af-radius-md: 10px; --af-radius-lg: 16px; --af-radius-xl: 24px; --af-radius-full: 9999px; } ``` ## Breakpoint Tokens [Section titled “Breakpoint Tokens”](#breakpoint-tokens) Breakpoint tokens define responsive breakpoints used by responsive suffixes (`@md`, `@lg`, etc.): ``` :root { --af-bp-xs: 360px; --af-bp-sm: 640px; --af-bp-md: 768px; --af-bp-lg: 1024px; --af-bp-xl: 1280px; --af-bp-2xl: 1536px; } ``` ## Shadow Tokens [Section titled “Shadow Tokens”](#shadow-tokens) Shadow tokens provide consistent elevation: ``` :root { --af-shadow-sm: 0 1px 2px rgba(0,0,0,.06); --af-shadow-md: 0 6px 16px rgba(0,0,0,.10); --af-shadow-lg: 0 16px 40px rgba(0,0,0,.14); } ``` ## Z-Index Tokens [Section titled “Z-Index Tokens”](#z-index-tokens) Z-index tokens provide a consistent layering system: ``` :root { --af-z-base: 0; --af-z-dropdown: 1000; --af-z-sticky: 1100; --af-z-overlay: 1200; --af-z-modal: 1300; --af-z-toast: 1400; } ``` ## Border Tokens [Section titled “Border Tokens”](#border-tokens) Border tokens control border width and hit target sizes: ``` :root { --af-border-width: 2px; --af-hit-size: 2.75rem; /* Minimum touch target size */ } ``` ## Layout Tokens [Section titled “Layout Tokens”](#layout-tokens) Layout tokens control container widths and layout spacing: ``` :root { --af-layout-gap: var(--af-space-4); --af-container-padding-x: var(--af-space-4); --af-container-max-w: 90em; /* 1440px - default container */ --af-container-max-w-xs: 25rem; /* 400px */ --af-container-max-w-sm: 40rem; /* 640px */ --af-container-max-w-md: 48rem; /* 768px */ --af-container-max-w-lg: 64rem; /* 1024px */ --af-container-max-w-xl: 80rem; /* 1280px */ --af-container-max-w-2xl: 96rem; /* 1536px */ } ``` ## Component Tokens [Section titled “Component Tokens”](#component-tokens) Component tokens are a thin, override-friendly layer for common sizing tweaks. They sit on top of global tokens so you can adjust buttons and form controls without rewriting styles. ### Shared Control Tokens [Section titled “Shared Control Tokens”](#shared-control-tokens) ``` :root { --af-control-min-height: auto; --af-control-radius: var(--af-radius-xl); --af-control-padding-y: var(--af-space-2); --af-control-padding-x: var(--af-space-3); --af-control-border: var(--af-color-border); /_ Choice controls (checkbox, radio, switch track height) _/ --af-choice-size: 1.5rem; --af-switch-height: var(--af-choice-size); --af-switch-width-ratio: 0.8; } ``` Checkbox and radio use `--af-choice-size`. Switches use `--af-switch-height` (defaults to choice size) and `--af-switch-width-ratio` for track width. ### Button Tokens [Section titled “Button Tokens”](#button-tokens) ``` :root { /* Button sizing */ --af-btn-min-height: var(--af-control-min-height); --af-btn-radius: var(--af-radius-full); --af-btn-padding-y: var(--af-control-padding-y); --af-btn-padding-x: var(--af-space-4); --af-btn-gap: var(--af-space-2); --af-btn-icon-size: 1.25em; --af-btn-font-weight: var(--af-weight-medium); --af-btn-border-width: var(--af-border-width); /_ Button colors (primary/default) _/ --af-btn-default-bg: var(--af-color-primary); --af-btn-default-color: var(--af-color-on-primary); --af-btn-default-hover: var(--af-color-primary-hover); --af-btn-default-active: var(--af-color-primary-active); /_ Button colors (secondary) _/ --af-btn-secondary-bg: var(--af-base-secondary); --af-btn-secondary-color: var(--af-color-on-secondary); --af-btn-secondary-hover: color-mix(in srgb, var(--af-btn-secondary-bg), black 4%); --af-btn-secondary-active: color-mix(in srgb, var(--af-btn-secondary-bg), black 8%); /_ Button colors (outline) _/ --af-btn-outline-color: var(--af-color-primary); --af-btn-outline-border: var(--af-color-primary); --af-btn-outline-hover: var(--af-btn-outline-border); --af-btn-outline-active: color-mix(in srgb, var(--af-color-primary), var(--af-color-surface-primary) 84%); } ``` ### Input Tokens [Section titled “Input Tokens”](#input-tokens) ``` :root { --af-input-min-height: var(--af-control-min-height); --af-input-radius: var(--af-control-radius); --af-input-padding-y: var(--af-control-padding-y); --af-input-padding-x: var(--af-control-padding-x); --af-input-font-size: var(--af-text-md); --af-input-leading: var(--af-leading-normal); --af-input-placeholder-color: var(--af-color-text-muted); } ``` ### Link Tokens [Section titled “Link Tokens”](#link-tokens) ``` :root { --af-link-primary: var(--af-color-primary); --af-link-hover-primary: var(--af-color-primary-hover); } ``` ### Card Tokens [Section titled “Card Tokens”](#card-tokens) ``` :root { --af-card-radius: var(--af-radius-lg); --af-card-padding: var(--af-space-4); --af-card-shadow: var(--af-shadow-sm); --af-card-shadow-hover: var(--af-shadow-md); } ``` ### Focus Ring Tokens [Section titled “Focus Ring Tokens”](#focus-ring-tokens) ``` :root { --af-focus-ring-color: var(--af-color-focus); --af-focus-ring-width: 2px; --af-focus-ring-offset: 2px; } ``` ### Example Override [Section titled “Example Override”](#example-override) ``` :root { --af-control-min-height: 3rem; --af-btn-gap: 0.75rem; --af-input-placeholder-color: rgba(0, 0, 0, 0.45); } ``` ## Motion Tokens [Section titled “Motion Tokens”](#motion-tokens) Motion tokens provide consistent timing for transitions and animations, with **automatic reduced motion support** built-in. ### Duration Variables [Section titled “Duration Variables”](#duration-variables) **Transition durations** (for CSS transitions): ``` :root { --af-duration-fast: 120ms; /* Quick interactions */ --af-duration-md: 200ms; /* Standard transitions */ --af-duration-slow: 320ms; /* Deliberate changes */ } ``` **Animation durations** (for keyframe animations): ``` :root { --af-animation-duration-fast: 200ms; /* Quick animations */ --af-animation-duration-md: 400ms; /* Standard animations */ --af-animation-duration-slow: 600ms; /* Slower animations */ --af-animation-duration-slower: 1500ms; /* Very slow animations */ } ``` ### Easing Functions [Section titled “Easing Functions”](#easing-functions) ``` :root { --af-ease-standard: cubic-bezier(.2, .0, .2, 1); /* Default easing */ --af-ease-emphasized: cubic-bezier(.2, .0, 0, 1); /* More pronounced */ --af-ease-in: cubic-bezier(.4, .0, 1, 1); /* Ease in */ --af-ease-out: cubic-bezier(.0, .0, .2, 1); /* Ease out */ --af-ease-in-out: cubic-bezier(.4, .0, .2, 1); /* Ease in-out */ --af-ease-linear: linear; /* Linear */ } ``` ### Usage Examples [Section titled “Usage Examples”](#usage-examples) **Transitions:** ``` /* Button hover transition */ .af-btn { transition: background-color var(--af-duration-fast) var(--af-ease-standard); } /_ Card shadow transition _/ .af-card { transition: box-shadow var(--af-duration-md) var(--af-ease-out); } /_ Multiple properties _/ .element { transition: background-color var(--af-duration-fast) var(--af-ease-standard), transform var(--af-duration-md) var(--af-ease-emphasized); } ``` **Animations:** ``` /* Spinner animation */ @keyframes spin { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } .af-spinner { animation: spin var(--af-animation-duration-md) var(--af-ease-linear) infinite; } /_ Skeleton loading animation _/ @keyframes skeleton-load { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } } .af-skeleton { animation: skeleton-load var(--af-animation-duration-slower) var(--af-ease-in-out) infinite; } ``` ### Reduced Motion Support [Section titled “Reduced Motion Support”](#reduced-motion-support) All motion tokens **automatically respect** the user’s `prefers-reduced-motion` preference. When reduced motion is enabled, all durations are set to `0.01ms` (effectively instant). **No additional code needed** - just use the tokens: ``` /* This automatically respects reduced motion */ .button { transition: background-color var(--af-duration-fast) var(--af-ease-standard); } /_ This also respects reduced motion _/ .spinner { animation: spin var(--af-animation-duration-md) linear infinite; } ``` **Customizing motion tokens:** ``` :root { /* Override default durations */ --af-duration-fast: 100ms; --af-animation-duration-slow: 800ms; /_ Custom easing _/ --af-ease-standard: cubic-bezier(0.4, 0, 0.2, 1); } ``` **Note:** The reduced motion override still applies even when you customize these values, ensuring accessibility is maintained. # Theming > Customize colors, tokens, and themes in Airframe Airframe uses tokens as CSS variables. Override them directly in CSS—no build step required. ## Theme Studio [Section titled “Theme Studio”](#theme-studio) Need to map an existing design system? Use **[Theme Studio](/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.css ``` AI / MCP: install `@airframeui/mcp` and use `generate_theme` → `lint_theme`. See `@airframeui/theme/rules` and [Build Tool](/docs/advanced/build#af-theme-theme-generation). ## Color Tokens [Section titled “Color Tokens”](#color-tokens) ### Override Primitives (Simplest) [Section titled “Override Primitives (Simplest)”](#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-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](#dark-mode) and [High Contrast](#high-contrast) sections for complete examples. ### Interaction States [Section titled “Interaction States”](#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”](#dark-mode) Airframe ships with dark tokens and follows system preference by default. ### Default Behavior [Section titled “Default Behavior”](#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”](#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-theme` attribute**: Standard data attribute * **`.dark` class**: CSS class ``` ... ... ... ``` ### Custom Dark Mode Colors [Section titled “Custom Dark Mode Colors”](#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](#color-tokens) for when to use each approach. ## High Contrast [Section titled “High Contrast”](#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”](#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](/resources/accessibility/color-contrast) before deploying. ### Available High Contrast Override Tokens [Section titled “Available High Contrast Override Tokens”](#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”](#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-tokens) Typography is driven by semantic tokens so brands can override safely: ### Font Families [Section titled “Font Families”](#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”](#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) 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) 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”](#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”](#next-steps) * [Tokens Reference](/docs/tokens) - Complete token documentation * [Advanced Overrides](/docs/advanced/overrides) - Deep customization # Layouts Layout recipes provide consistent patterns for organizing content. They replace verbose utility classes with semantic, readable class names. ## Stack [Section titled “Stack”](#stack) Vertical stacking layout for arranging items in a column. ### Class Reference [Section titled “Class Reference”](#class-reference) | Class | Purpose | Gap Size | Example | | ------------- | ---------------------- | ----------------- | --------------------------- | | `af-stack` | Default vertical stack | Medium (`gap-md`) | `
` | | `af-stack-sm` | Small gap stack | Small (`gap-sm`) | `
` | | `af-stack-md` | Medium gap stack | Medium (`gap-md`) | `
` | | `af-stack-lg` | Large gap stack | Large (`gap-lg`) | `
` | | `af-stack-xl` | Extra large gap stack | XL (`gap-xl`) | `
` | ### Basic Stack [Section titled “Basic Stack”](#basic-stack) Code Live ```
Item 1
Item 2
Item 3
``` Item 1 Item 2 Item 3 ### Stack Sizes [Section titled “Stack Sizes”](#stack-sizes) Code Live ```
Small spacing
Default spacing (md)
Medium spacing (same as default)
Large spacing
``` Small gap Small gap Default gap Default gap Large gap Large gap ### Live Examples [Section titled “Live Examples”](#live-examples) Basic stack (default gap-md): Item 1 Item 2 Item 3 Stack sizes: Small gap Small gap Default gap Default gap Large gap Large gap ## Inline [Section titled “Inline”](#inline) Horizontal layout with wrapping for arranging items in a row. ### Class Reference [Section titled “Class Reference”](#class-reference-1) | Class | Purpose | Gap Size | Example | | -------------- | ----------------------- | ----------------- | ---------------------------- | | `af-inline` | Default horizontal wrap | Medium (`gap-md`) | `
` | | `af-inline-sm` | Small gap inline | Small (`gap-sm`) | `
` | | `af-inline-md` | Medium gap inline | Medium (`gap-md`) | `
` | | `af-inline-lg` | Large gap inline | Large (`gap-lg`) | `
` | | `af-inline-xl` | Extra large gap inline | XL (`gap-xl`) | `
` | ### Basic Inline [Section titled “Basic Inline”](#basic-inline) Code Live ```
``` Button 1 Button 2 Button 3 ### Inline Sizes [Section titled “Inline Sizes”](#inline-sizes) Code Live ```
Small spacing
Default spacing (md)
Large spacing
XL spacing
``` Small Gap Default Gap Large Gap XL Gap ### Inline with Justify Content [Section titled “Inline with Justify Content”](#inline-with-justify-content) Code Live ```
Start aligned
Center aligned
End aligned
Space between
``` Start Aligned Center Aligned End Aligned Space Between ### Live Examples [Section titled “Live Examples”](#live-examples-1) Basic inline (default gap-md): Button 1Button 2Button 3 Inline sizes: SmallGap DefaultGap LargeGap XLGap Justify content: StartAligned CenterAligned EndAligned SpaceBetween ## Cluster, Spread & Center [Section titled “Cluster, Spread & Center”](#cluster-spread--center) **Layout primitives vs Display utilities:** `af-cluster`, `af-spread`, and `af-center` are **semantic layout recipes** — each combines display, alignment, and gap in one class. They live in [Layouts](/docs/layouts) (this page). The [Display & Alignment](/docs/utilities/display) utilities (`af-flex`, `af-justify-*`, `af-items-*`) are **low-level building blocks** — use them when you need custom combinations (e.g. `af-inline af-justify-end`). Prefer layout recipes first; reach for utilities when you need fine-grained control. | Recipe | Equivalent utilities | Use when | | ------------ | ----------------------------------------------------------------------------------- | -------------------------------- | | `af-cluster` | `af-inline af-items-center af-gap-md` | Tags, chips, grouped buttons | | `af-spread` | `af-inline af-items-center af-justify-between` | Header left/right, space-between | | `af-center` | `af-flex af-justify-center af-items-center` or `display: grid; place-items: center` | Centering content on both axes | Cluster and spread are lightweight inline layout recipes for common alignment patterns. Default to these semantic recipes, and use explicit alignment utilities when you need fine-grained control. ### Class Reference [Section titled “Class Reference”](#class-reference-2) | Class | Purpose | Example | | ------------ | ---------------------------------------- | -------------------------- | | `af-cluster` | Inline cluster (wrap + center alignment) | `
` | | `af-spread` | Inline spread (space-between) | `
` | ### Examples [Section titled “Examples”](#examples) Code Live ```
Tag 1 Tag 2 Tag 3
Left Right
``` Tag 1 Tag 2 Tag 3 Left Right **Explicit equivalents (when needed):** Code Live ```
Cluster content Cluster content
Left Right
``` Cluster content Cluster content Left Right ## Cover & Sidebar [Section titled “Cover & Sidebar”](#cover--sidebar) **Cover** - Full-viewport hero layout (min-height: 100dvh, centered content): Code Live ```

Hero

Centered full-viewport layout

``` # Hero Centered full-viewport layout **Sidebar** - Main content + sidebar (stacks on mobile, side-by-side on tablet+): Code Live ```
Main content (1fr)
``` Main content Sidebar ## Center [Section titled “Center”](#center) Centers content horizontally and vertically. Code Live ```

Centered

``` Centered **Explicit equivalent:** Code Live ```

Centered

``` Centered ## Container [Section titled “Container”](#container) Centered content wrapper with max-width and horizontal padding. Use **one class** per element. | Class | Max Width | Use Case | | ------------------ | -------------- | ------------------------------ | | `af-container` | 90em (1440px) | Default, standard page content | | `af-container-xs` | 25rem (400px) | Narrow forms, sidebars | | `af-container-sm` | 40rem (640px) | Narrow content | | `af-container-md` | 48rem (768px) | Tablet-optimized | | `af-container-lg` | 64rem (1024px) | Desktop content | | `af-container-xl` | 80rem (1280px) | Wide layouts | | `af-container-2xl` | 96rem (1536px) | Extra-wide layouts | **Tip:** Use **one class only**. `af-container-xl` is enough. Do not combine `af-container af-container-xl`. For responsive sizing, use the responsive suffix: `af-container af-container-lg@xl` (default on mobile, large at xl breakpoint). ### Basic Container [Section titled “Basic Container”](#basic-container) Code Live ```
``` Container content with default max-width (90em / 1440px) ### Container Sizes [Section titled “Container Sizes”](#container-sizes) Code Live ```
Extra small (400px max)
Small (640px max)
Medium (768px max)
Large (1024px max)
Extra large (1280px max)
``` xs - 400px max sm - 640px max md - 768px max lg - 1024px max xl - 1280px max ### Live Examples [Section titled “Live Examples”](#live-examples-2) Default container: Container content with default max-width (90em / 1440px) Container sizes: xs - 400px max sm - 640px max md - 768px max lg - 1024px max xl - 1280px max ## Surface [Section titled “Surface”](#surface) Surface pattern for creating simple containers with background, border, and border-radius. Unlike cards, surfaces don’t include padding or shadows—you add those yourself. ### Basic Surface [Section titled “Basic Surface”](#basic-surface) Code Live ```

Surface with padding added

``` Surface with padding added ### Surface Variants [Section titled “Surface Variants”](#surface-variants) Use `af-is-*` modifier classes to change the surface background: Code Live ```
Default surface (primary)
Secondary surface
Tertiary surface
``` Default surface (primary background) Secondary surface variant Tertiary surface variant ### When to Use Surface vs Card [Section titled “When to Use Surface vs Card”](#when-to-use-surface-vs-card) * **Surface** (`af-surface`): Simple container without padding or shadow. Use for panels, backgrounds, or when you need full control over spacing. * **Card** (`af-card`): Full component with padding, shadow, and semantic parts. Use for content containers with structure. ### Live Example [Section titled “Live Example”](#live-example) Default surface (primary background) Secondary surface variant Tertiary surface variant ## Section [Section titled “Section”](#section) Section pattern for consistent vertical spacing between page sections. Adds padding-block (top and bottom padding) to create visual separation. ### Basic Section [Section titled “Basic Section”](#basic-section) Code Live ```

Section Title

Section content

``` ### Section Title Section content ### Section Sizes & Variants [Section titled “Section Sizes & Variants”](#section-sizes--variants) Code Live ```
Small spacing
Default spacing
Large spacing
Hero (extra padding)
Alternate background
Narrow container
``` ### Small Section Reduced vertical spacing (space-4) ### Default Section Standard vertical spacing (space-6) ### Large Section Increased vertical spacing (space-8) ### Section Variants [Section titled “Section Variants”](#section-variants) * `af-section-hero` - Extra padding for hero sections * `af-section-alt` - Alternate background (`--af-color-surface-primary`) * `af-section-narrow` - Constrains child `.af-container` to `--af-container-max-w-md` ### Use Cases [Section titled “Use Cases”](#use-cases) * Page sections with consistent spacing * Content areas that need vertical rhythm * Separating major content blocks ### Live Example [Section titled “Live Example”](#live-example-1) ### Small Section Reduced vertical spacing (space-4) ### Default Section Standard vertical spacing (space-6) ### Large Section Increased vertical spacing (space-8) ## Spacer [Section titled “Spacer”](#spacer) Utility for adding vertical spacing (margin-block) between elements. Useful when you need spacing but don’t want to use a full stack layout. ### Basic Usage [Section titled “Basic Usage”](#basic-usage) Code Live ```
Content
Small spacer above
Content
Medium spacer above
Content
Large spacer above
``` Content Small spacer above Content Medium spacer above Content Large spacer above Content ### Spacer Sizes [Section titled “Spacer Sizes”](#spacer-sizes) * `af-spacer-sm` - Small spacing (space-2) * `af-spacer-md` - Medium spacing (space-4) * `af-spacer-lg` - Large spacing (space-6) ### When to Use [Section titled “When to Use”](#when-to-use) * Adding spacing between individual elements * Creating gaps in non-stack layouts * Quick vertical rhythm without changing layout structure **Note:** For consistent vertical layouts, prefer `af-stack` with gap utilities. Use spacer for one-off spacing needs. ### Live Example [Section titled “Live Example”](#live-example-2) Content Small spacer above Content Medium spacer above Content Large spacer above Content ## Position [Section titled “Position”](#position) Position utilities for controlling element positioning and placement. ### Position Values [Section titled “Position Values”](#position-values) Code Live ```
Relative positioning
Absolute positioning
Sticky positioning
Revert to default
``` Relative container ### Shorthand Classes [Section titled “Shorthand Classes”](#shorthand-classes) Code Live ```
Relative (shorthand)
Absolute (shorthand)
Sticky (shorthand)
``` Relative (shorthand) ### Position Offsets [Section titled “Position Offsets”](#position-offsets) Code Live ```
Top-left corner
Top-right corner
Bottom-left corner
Bottom-right corner
``` Top-left Top-right Bottom-left Bottom-right Relative container ### Available Classes [Section titled “Available Classes”](#available-classes) **Position:** * `af-pos-relative` / `af-relative` - `position: relative` * `af-pos-absolute` / `af-absolute` - `position: absolute` * `af-pos-sticky` / `af-sticky` - `position: sticky` * `af-pos-revert` - `position: revert` **Offsets:** * `af-inset-0` - `inset: 0` (all edges) * `af-top-0` - `top: 0` * `af-right-0` - `right: 0` * `af-bottom-0` - `bottom: 0` * `af-left-0` - `left: 0` ### Live Example [Section titled “Live Example”](#live-example-3) Top-left Top-right Bottom-left Bottom-right Relative container ## Responsive Suffixes [Section titled “Responsive Suffixes”](#responsive-suffixes) All layout classes support responsive variants using the `@{bp}` suffix. See [Responsive Suffix](/docs/responsive-suffix) for the full syntax and breakpoint table. Code Live ```
``` Medium gap on mobile, large gap on tablet+ Item 2 ## Flex Alignment Utilities [Section titled “Flex Alignment Utilities”](#flex-alignment-utilities) Control alignment in flex containers: ### Justify Content (Horizontal Alignment) [Section titled “Justify Content (Horizontal Alignment)”](#justify-content-horizontal-alignment) Code Live ```
Start
Center
End
Space Between
Space Around
Space Evenly
``` Start Aligned Center Aligned End Aligned Space Between ### Align Items (Vertical Alignment) [Section titled “Align Items (Vertical Alignment)”](#align-items-vertical-alignment) Code Live ```
Start
Center
End
Stretch
Baseline
``` Start Aligned Center Aligned End Aligned ### Responsive Alignment [Section titled “Responsive Alignment”](#responsive-alignment) Code Live ```
Start on mobile, center on tablet+
``` Start on mobile Center on tablet+ ### Live Example [Section titled “Live Example”](#live-example-4) Justify content examples: StartAligned CenterAligned EndAligned SpaceBetween Align items examples: StartAligned CenterAligned EndAligned ## Masonry (Experimental) [Section titled “Masonry (Experimental)”](#masonry-experimental) Masonry layout creates a waterfall-style layout where items flow into columns based on their height, similar to Pinterest-style layouts. ⚠️ **Experimental Feature** - Uses CSS Grid Lanes, which has very limited browser support. See [Browser Support](/docs/browser-support) for details. ### Browser Support [Section titled “Browser Support”](#browser-support) * ✅ **Safari Technology Preview 234+** (December 2025) - Full support * ⚠️ **Chrome 140+** - Available behind experimental flag * ⚠️ **Firefox 147+** - Available behind experimental flag * ⚠️ **Edge** - Available behind experimental flag **Fallback:** In unsupported browsers, automatically falls back to regular CSS Grid (items display in a standard grid, not masonry). ### Class Reference [Section titled “Class Reference”](#class-reference-3) | Class | Purpose | Column Width | Example | | ----------------- | ------------------- | ------------- | ------------------------------- | | `af-masonry` | Default masonry | 250px minimum | `
` | | `af-masonry-sm` | Small columns | 200px minimum | `
` | | `af-masonry-md` | Medium columns | 250px minimum | `
` | | `af-masonry-lg` | Large columns | 300px minimum | `
` | | `af-masonry-xl` | Extra large columns | 400px minimum | `
` | | `af-masonry-text` | Text-optimized | 20ch minimum | `
` | ### Basic Masonry [Section titled “Basic Masonry”](#basic-masonry) Code Live ```
Item 1
Item 2
Item 3
Item 4
``` ### Card 1 Short content ### Card 2 This card has more content to demonstrate how masonry layouts work. ### Card 3 Medium content ### Card 4 Another short card ### Masonry Variants [Section titled “Masonry Variants”](#masonry-variants) Code Live ```
Small columns (200px min)
Default columns (250px min)
Large columns (300px min)
Extra large columns (400px min)
Text-optimized (20ch min)
``` ### Card 1 Short content ### Card 2 This card has more content to demonstrate how masonry layouts work. Items flow into columns based on their height. ### Card 3 Medium content here ### Card 4 Another short card ### Live Example [Section titled “Live Example”](#live-example-5) ### Card 1 Short content ### Card 2 This card has more content to demonstrate how masonry layouts work. Items flow into columns based on their height. ### Card 3 Medium content here ### Card 4 Another short card ### Card 5 This is a longer card with more content to show how items of different heights flow into the masonry layout. The browser automatically places each item in the column that gets it closest to the top. ### Card 6 Short ### When to Use [Section titled “When to Use”](#when-to-use-1) * Photo galleries with varying image heights * Card layouts with different content lengths * Article teasers or blog post previews * Product listings with varying descriptions ### Polyfill for Production [Section titled “Polyfill for Production”](#polyfill-for-production) For production use in unsupported browsers, consider using a JavaScript polyfill: ``` // Feature detect and load polyfill if needed if (!CSS.supports('display', 'grid-lanes')) { import('masonry-layout').then(({ default: Masonry }) => { const grids = document.querySelectorAll('.af-masonry'); grids.forEach(grid => { new Masonry(grid, { itemSelector: '> *', columnWidth: 250, gutter: 16 }); }); }); } ``` See [Browser Support](/docs/browser-support#masonry-layout-grid-lanes-experimental) for more details. ## Gap Utilities [Section titled “Gap Utilities”](#gap-utilities) Control spacing between grid items or flex items: **Source of truth:** Gap utilities are defined in `grid.css` and documented in [Grid](/docs/grid). | Class | Gap Size | Token Value | Example | | ------------ | ---------------- | -------------- | -------------------------------------------- | | `af-gap-0` | No gap | `--af-space-0` | `
` | | `af-gap-xs` | Extra small | `--af-space-1` | `
` | | `af-gap-sm` | Small | `--af-space-2` | `
` | | `af-gap-lg` | Large | `--af-space-4` | `
` | | `af-gap-xl` | Extra large | `--af-space-5` | `
` | | `af-gap-2xl` | 2XL | `--af-space-6` | `
` | | `af-gap-3xl` | 3XL | `--af-space-7` | `
` | | `af-gap-4xl` | 4XL | `--af-space-8` | `
` | | (default) | Medium (default) | `--af-space-3` | `
` | **Usage:** Gap utilities can override default gaps in any layout recipe: Code Live ```
Override stack's default gap
Override inline's default gap
Override grid's default gap
``` Override stack's default gap (large) Item 2 ## Complete Class Reference [Section titled “Complete Class Reference”](#complete-class-reference) All classes available in `layouts.css`: ### Stack Classes (5) [Section titled “Stack Classes (5)”](#stack-classes-5) * `af-stack` - Default vertical stack (medium gap) * `af-stack-sm` - Small gap vertical stack * `af-stack-md` - Medium gap vertical stack (same as default) * `af-stack-lg` - Large gap vertical stack * `af-stack-xl` - Extra large gap vertical stack ### Inline Classes (5) [Section titled “Inline Classes (5)”](#inline-classes-5) * `af-inline` - Default horizontal wrap (medium gap) * `af-inline-sm` - Small gap horizontal wrap * `af-inline-md` - Medium gap horizontal wrap (same as default) * `af-inline-lg` - Large gap horizontal wrap * `af-inline-xl` - Extra large gap horizontal wrap ### Cluster / Spread / Center Classes (3) [Section titled “Cluster / Spread / Center Classes (3)”](#cluster--spread--center-classes-3) * `af-cluster` - Inline cluster (wrap + center alignment) * `af-spread` - Inline spread (space-between) * `af-center` - Center contents on both axes ### Container Classes (7) [Section titled “Container Classes (7)”](#container-classes-7) * `af-container` - Default container (90em / 1440px max-width) * `af-container-xs` - Extra small container (400px max-width) * `af-container-sm` - Small container (640px max-width) * `af-container-md` - Medium container (768px max-width) * `af-container-lg` - Large container (1024px max-width) * `af-container-xl` - Extra large container (1280px max-width) * `af-container-2xl` - 2xl container (1536px max-width) ### Gap Utilities (9) [Section titled “Gap Utilities (9)”](#gap-utilities-9) * `af-gap-0` - No gap * `af-gap-xs` - Extra small gap * `af-gap-sm` - Small gap * `af-gap-md` - Medium gap * `af-gap-lg` - Large gap * `af-gap-xl` - Extra large gap * `af-gap-2xl` / `af-gap-3xl` / `af-gap-4xl` - Larger gaps (`--af-space-6`…`8`) **Total: 29 layout classes** - All support responsive variants with `@` suffix (e.g., `af-stack@md`) **Note:** Grid classes are documented separately. See [Grid](/docs/grid) for complete grid documentation. ## Best Practices [Section titled “Best Practices”](#best-practices) * Use `af-stack` for vertical layouts * Use `af-inline` for horizontal wrapping layouts * See [Grid](/docs/grid) for grid layouts (equal columns and 12-column system) * Prefer layout recipes (`af-stack`, `af-inline`, `af-grid`, `af-container`) over many atomic utility classes * Use responsive suffixes for breakpoint-specific styles * Combine layout recipes with pattern classes for complex layouts * Use `af-justify-*` and `af-items-*` for fine-grained alignment control ## Next Steps [Section titled “Next Steps”](#next-steps) * [Grid](/docs/grid) — equal columns and the 12-column system * [Responsive Suffix](/docs/responsive-suffix) — breakpoint variants with `@` * [Recipes](/docs/recipes) — copy-paste page compositions built from these primitives # Framework Support > Using Airframe with React, Angular, Next.js, Vue, and vanilla HTML Airframe is CSS-only and framework-agnostic. Install the core package and use it with any framework or vanilla HTML. ## Install [Section titled “Install”](#install) ``` npm install @airframeui/core ``` ``` @import "@airframeui/core/core.css"; ``` ``` ``` ## React [Section titled “React”](#react) ``` /* src/index.css */ @import "@airframeui/core/core.css"; ``` ``` function App() { return (
) } ``` See [React Recipes](/docs/react-recipes) for copy-paste ready components. ## Next.js [Section titled “Next.js”](#nextjs) ### App Router [Section titled “App Router”](#app-router) ``` /* app/globals.css */ @import "@airframeui/core/core.css"; ``` ``` // app/layout.tsx import './globals.css' export default function RootLayout({ children }) { return ( {children} ) } ``` ### Pages Router [Section titled “Pages Router”](#pages-router) ``` /* styles/globals.css */ @import "@airframeui/core/core.css"; ``` ``` // pages/_app.tsx import '../styles/globals.css' export default function App({ Component, pageProps }) { return } ``` See [Next.js Setup](/docs/nextjs) for a complete guide. ## Angular [Section titled “Angular”](#angular) ``` npm install @airframeui/core ``` Add to `angular.json` under `projects..architect.build.options`: ``` "styles": [ "node_modules/@airframeui/core/core.css", "src/styles.scss" ] ``` Use directly in templates: ``` @Component({ selector: 'app-dashboard', standalone: true, template: `

Dashboard

Revenue

$84,200

` }) export class DashboardComponent {} ``` See [Angular Setup](/docs/angular) for a complete guide. ## Vue [Section titled “Vue”](#vue) ``` /* src/main.css */ @import "@airframeui/core/core.css"; ``` ``` ``` ## Vanilla HTML [Section titled “Vanilla HTML”](#vanilla-html) ``` ``` ## Next Steps [Section titled “Next Steps”](#next-steps) * [Installation](/docs/installation) - Get started * [Usage](/docs/usage) - Learn the basics * [Angular Setup](/docs/angular) - Angular specific guide * [Next.js Setup](/docs/nextjs) - Next.js specific guide * [React Recipes](/docs/react-recipes) - React examples # Angular Setup Guide > Using Airframe with Angular standalone and NgModule applications Airframe is CSS-only. No Angular-specific package needed. Install the core CSS, import it, and use Airframe classes directly in your templates. Works with Angular 17+ standalone components and NgModule applications. ## Quick Start [Section titled “Quick Start”](#quick-start) ### 1. Install [Section titled “1. Install”](#1-install) ``` npm install @airframeui/core ``` ### 2. Import CSS [Section titled “2. Import CSS”](#2-import-css) **Using angular.json (recommended)** Add to `angular.json` under `projects..architect.build.options`: ``` "styles": [ "node_modules/@airframeui/core/core.css", "src/styles.scss" ] ``` **Using styles.scss** Alternatively, import directly in `src/styles.scss`: ``` @import "@airframeui/core/core.css"; ``` ### 3. Use in templates [Section titled “3. Use in templates”](#3-use-in-templates) ``` @Component({ selector: 'app-root', standalone: true, template: `

Welcome

` }) export class AppComponent {} ``` That’s it. No wrappers, no modules to import, no extra dependencies. ## Standalone Component Examples [Section titled “Standalone Component Examples”](#standalone-component-examples) ### Dashboard Layout [Section titled “Dashboard Layout”](#dashboard-layout) ``` @Component({ selector: 'app-dashboard', standalone: true, template: `

Dashboard

Revenue

$84,200

Users

12,340

Growth

+18%

Main Content

Content goes here

Sidebar

Sidebar content

` }) export class DashboardComponent {} ``` ### Form with Reactive Forms [Section titled “Form with Reactive Forms”](#form-with-reactive-forms) ``` import { Component } from '@angular/core'; import { ReactiveFormsModule, FormBuilder, Validators } from '@angular/forms'; @Component({ selector: 'app-contact', standalone: true, imports: [ReactiveFormsModule], template: `

We'll never share your email.

` }) export class ContactComponent { form = inject(FormBuilder).group({ name: ['', Validators.required], email: ['', [Validators.required, Validators.email]], message: ['', Validators.required], }); onSubmit(): void { console.log(this.form.value); } } ``` ### Navigation with Router [Section titled “Navigation with Router”](#navigation-with-router) ``` import { Component } from '@angular/core'; import { RouterLink, RouterLinkActive, RouterOutlet } from '@angular/router'; @Component({ selector: 'app-layout', standalone: true, imports: [RouterLink, RouterLinkActive, RouterOutlet], template: `
` }) export class LayoutComponent {} ``` ### Data Table [Section titled “Data Table”](#data-table) ``` import { Component, input } from '@angular/core'; @Component({ selector: 'app-user-table', standalone: true, template: `
@for (user of users(); track user.id) { }
Name Email Role Actions
{{ user.name }} {{ user.email }} {{ user.role }}
` }) export class UserTableComponent { users = input<{ id: number; name: string; email: string; role: string }[]>([]); } ``` ## Theming [Section titled “Theming”](#theming) ### Custom tokens [Section titled “Custom tokens”](#custom-tokens) Override tokens in your `styles.scss`. No rebuild needed. ``` /* src/styles.scss */ @import "@airframeui/core/core.css"; :root { --af-base-primary: #0066cc; --af-font-body: 'Inter', sans-serif; --af-radius-md: 0.5rem; } ``` ### Dark mode [Section titled “Dark mode”](#dark-mode) Dark mode follows system preference by default. Override per-element or globally: ```
Dark card on a light page
``` Available themes: `light`, `dark`, `high-contrast-light`, `high-contrast-dark` ### Dynamic theme switching [Section titled “Dynamic theme switching”](#dynamic-theme-switching) ``` @Component({ selector: 'app-theme-toggle', standalone: true, template: ` ` }) export class ThemeToggleComponent { isDark = false; toggleTheme(): void { this.isDark = !this.isDark; document.documentElement.setAttribute( 'data-theme', this.isDark ? 'dark' : 'light' ); } } ``` ## View Encapsulation [Section titled “View Encapsulation”](#view-encapsulation) Airframe classes work with Angular’s default view encapsulation. If you need to style Airframe elements from a parent component, use `:host` or set encapsulation to `None`: ``` @Component({ selector: 'app-custom', standalone: true, encapsulation: ViewEncapsulation.None, styles: ` .my-custom-card { --af-card-padding: var(--af-space-6); --af-card-radius: var(--af-radius-lg); } `, template: `

Custom Card

` }) export class CustomComponent {} ``` ## SSR (Angular Universal) [Section titled “SSR (Angular Universal)”](#ssr-angular-universal) Airframe CSS works with Angular SSR out of the box. No special configuration needed. The CSS is loaded via `angular.json` styles array, which works in both client and server builds. ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) ### CSS not loading [Section titled “CSS not loading”](#css-not-loading) * Check that `@airframeui/core/core.css` is in the `styles` array in `angular.json` * Or check that `src/styles.scss` imports it and is itself in the `styles` array ### Styles not applying [Section titled “Styles not applying”](#styles-not-applying) 1. Use `class` not `className` (Angular uses `class`) 2. Check that no conflicting CSS is overriding Airframe styles 3. If view encapsulation is blocking styles, override tokens via CSS variables instead of targeting Airframe class internals ### Build errors [Section titled “Build errors”](#build-errors) * Angular 17+ required * Node 20+ required by the Angular CLI toolchain (Airframe CSS itself has no Node runtime requirement) * Run `npm install` to ensure `@airframeui/core` is installed ## Next Steps [Section titled “Next Steps”](#next-steps) * [Patterns](/docs/patterns/button) - See all available patterns * [Tokens](/docs/tokens) - Customise your theme * [Layouts](/docs/layouts) - Structural primitives * [Accessibility](/docs/accessibility) - Built-in accessibility # Next.js Setup Guide Airframe works seamlessly with Next.js in both App Router and Pages Router. ## Quick Start [Section titled “Quick Start”](#quick-start) ### 1. Install [Section titled “1. Install”](#1-install) ``` npm install @airframeui/core # or pnpm add @airframeui/core ``` ### 2. Import CSS [Section titled “2. Import CSS”](#2-import-css) #### App Router (app directory) [Section titled “App Router (app directory)”](#app-router-app-directory) Create or update `app/globals.css`: ``` @import "@airframeui/core/core.css"; ``` Then import it in `app/layout.tsx`: ``` import './globals.css' export default function RootLayout({ children, }: { children: React.ReactNode }) { return ( {children} ) } ``` #### Pages Router (pages directory) [Section titled “Pages Router (pages directory)”](#pages-router-pages-directory) Create or update `styles/globals.css`: ``` @import "@airframeui/core/core.css"; ``` Then import it in `pages/_app.tsx`: ``` import '../styles/globals.css' import type { AppProps } from 'next/app' export default function App({ Component, pageProps }: AppProps) { return } ``` ### 3. Use Patterns [Section titled “3. Use Patterns”](#3-use-patterns) Now you can use Airframe classes anywhere: ``` // app/page.tsx (App Router) or pages/index.tsx (Pages Router) export default function Home() { return (

Welcome

) } ``` ## App Router Examples [Section titled “App Router Examples”](#app-router-examples) ### Basic Page [Section titled “Basic Page”](#basic-page) ``` // app/dashboard/page.tsx export default function Dashboard() { return (

Dashboard

Main Content

Content goes here

Sidebar

Sidebar content

) } ``` ### Server Component with Forms [Section titled “Server Component with Forms”](#server-component-with-forms) ``` // app/contact/page.tsx export default function Contact() { return (