Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
250 changes: 142 additions & 108 deletions .claude/skills/design-system/references/token-architecture.md
Original file line number Diff line number Diff line change
@@ -1,93 +1,113 @@
# Token Architecture
# Token Architecture — Andritz Precision

Three-layer token system for scalable, themeable design systems.
Three-layer token system for the Andritz industrial design system with dark/light theme support.

## Layer Overview

```
┌─────────────────────────────────────────┐
│ Component Tokens │ Per-component overrides
│ --button-bg, --card-padding
│ Component Tokens │ Andritz component overrides
│ --button-bg, --card-bg, --input-bg
├─────────────────────────────────────────┤
│ Semantic Tokens │ Purpose-based aliases
│ --color-primary, --spacing-section
│ Semantic Tokens │ Surface hierarchy + purpose aliases
│ --color-surface, --color-primary
├─────────────────────────────────────────┤
│ Primitive Tokens │ Raw design values
│ --color-blue-600, --space-4
│ Primitive Tokens │ Andritz raw values
│ --andritz-blue-500, --surface-low
└─────────────────────────────────────────┘
```

## Why Three Layers?

| Layer | Purpose | When to Change |
|-------|---------|----------------|
| Primitive | Base values (colors, sizes) | Rarely - foundational |
| Semantic | Meaning assignment | Theme switching |
| Component | Component customization | Per-component needs |
| Primitive | Andritz brand values (blues, surfaces, neutrals) | Rarely foundational |
| Semantic | Surface hierarchy + purpose aliases | Theme switching (light/dark) |
| Component | Industrial component customization | Per-component needs |

## Layer 1: Primitive Tokens

Raw design values without semantic meaning.
Raw Andritz design values without semantic meaning.

```css
:root {
/* Colors */
--color-gray-50: #F9FAFB;
--color-gray-900: #111827;
--color-blue-500: #3B82F6;
--color-blue-600: #2563EB;

/* Spacing (4px base) */
--space-1: 0.25rem; /* 4px */
--space-2: 0.5rem; /* 8px */
--space-4: 1rem; /* 16px */
--space-6: 1.5rem; /* 24px */
/* Andritz Blue Scale */
--andritz-blue-900: #001c38;
--andritz-blue-700: #004a77;
--andritz-blue-600: #005c97;
--andritz-blue-500: #0075be;
--andritz-blue-300: #9bcaff;
--andritz-blue-200: #c6dfff;

/* Surface Scale (Light) */
--surface-lowest: #ffffff;
--surface-low: #f8fafb;
--surface-base: #f2f4f5;
--surface-mid: #eceeef;
--surface-high: #e6e8e9;
--surface-highest: #e1e3e4;

/* Neutral Scale */
--neutral-950: #001c38; /* deepest black — never use pure #000000 */
--neutral-900: #191c1d;
--neutral-700: #404751;
--neutral-300: #c0c7d2;
--neutral-200: #dfe2eb;

/* Spacing (8px grid, extreme whitespace) */
--space-2: 0.5rem; /* 8px */
--space-4: 1rem; /* 16px */
--space-6: 1.5rem; /* 24px */
--space-8: 2rem; /* 32px — zone separation */

/* Typography */
--font-size-sm: 0.875rem;
--font-size-base: 1rem;
--font-size-lg: 1.125rem;

/* Radius */
--radius-sm: 0.25rem;
--radius-default: 0.5rem;
--radius-lg: 0.75rem;

/* Shadows */
--shadow-sm: 0 1px 2px rgb(0 0 0 / 0.05);
--shadow-default: 0 1px 3px rgb(0 0 0 / 0.1);
--font-family-primary: 'Inter', system-ui, sans-serif;
--font-size-display-lg: 3.5rem;
--font-size-label-md: 0.75rem;

/* Radius — Industrial Precision: 0px */
--radius-none: 0;
--radius-full: 9999px;

/* Shadow — Ambient only */
--shadow-ambient-light: 0px 12px 32px 0px rgba(0, 28, 56, 0.06);
--shadow-ambient-dark: 0px 12px 32px 0px rgba(0, 28, 56, 0.4);
}
```

## Layer 2: Semantic Tokens

Purpose-based aliases that reference primitives.
Purpose-based aliases that reference primitives. The surface hierarchy creates depth through tonal stacking.

```css
:root {
/* Background */
--color-background: var(--color-gray-50);
--color-foreground: var(--color-gray-900);
/* Surface Hierarchy — "Machined Plates" */
--color-surface: var(--surface-low); /* #f8fafb */
--color-surface-container: var(--surface-mid); /* #eceeef */
--color-surface-container-low: var(--surface-base); /* #f2f4f5 */
--color-surface-container-high: var(--surface-high); /* #e6e8e9 */
--color-surface-container-highest: var(--surface-highest); /* #e1e3e4 */
--color-surface-container-lowest: var(--surface-lowest); /* #ffffff */

/* Primary */
--color-primary: var(--color-blue-600);
--color-primary-hover: var(--color-blue-700);
/* Primary (Andritz Blue) */
--color-primary: var(--andritz-blue-500); /* #0075be — action containers */
--color-primary-text: var(--andritz-blue-600); /* #005c97 — text/iconography */
--color-on-primary: #ffffff;

/* Secondary */
--color-secondary: var(--color-gray-100);
--color-secondary-foreground: var(--color-gray-900);
/* Text */
--color-on-surface: var(--neutral-900); /* #191c1d */
--color-on-surface-variant: var(--neutral-700); /* #404751 */

/* Muted */
--color-muted: var(--color-gray-100);
--color-muted-foreground: var(--color-gray-500);
/* Outline (Ghost Border) */
--color-outline-variant: var(--neutral-300); /* at 15% opacity */

/* Destructive */
--color-destructive: var(--color-red-600);
--color-destructive-foreground: white;
/* Border */
--color-border: transparent; /* No-Line Rule */

/* Spacing */
--spacing-component: var(--space-4);
--spacing-section: var(--space-6);
--spacing-zone: var(--space-8); /* 32px zone separation */
--spacing-section: var(--space-12); /* 48px */
}
```

Expand All @@ -97,83 +117,97 @@ Component-specific tokens referencing semantic layer.

```css
:root {
/* Button */
--button-bg: var(--color-primary);
--button-fg: white;
--button-hover-bg: var(--color-primary-hover);
--button-padding-x: var(--space-4);
--button-padding-y: var(--space-2);
--button-radius: var(--radius-default);

/* Input */
--input-bg: var(--color-background);
--input-border: var(--color-gray-300);
--input-focus-ring: var(--color-primary);
--input-padding: var(--space-2) var(--space-3);

/* Card */
--card-bg: var(--color-background);
--card-border: var(--color-gray-200);
--card-padding: var(--space-4);
--card-radius: var(--radius-lg);
--card-shadow: var(--shadow-default);
/* Button — Gradient CTA, 0px radius */
--button-bg: linear-gradient(135deg, var(--color-primary-text), var(--color-primary));
--button-fg: var(--color-on-primary);
--button-radius: 0px;
--button-padding-x: var(--space-6); /* 24px — heavy horizontal */
--button-active-scale: 0.98;

/* Input — Bottom-border focus, ledger style */
--input-bg: var(--color-surface-container-highest);
--input-focus-border: 2px solid var(--color-primary); /* bottom only */
--input-radius: 0px;

/* Card — Elevated surface, no borders */
--card-bg: var(--color-surface-container-lowest);
--card-border: none; /* No-Line Rule */
--card-radius: 0px;
--card-shadow: none; /* tonal stacking, not shadows */
}
```

## Dark Mode

Override semantic tokens for dark theme:
Override semantic tokens for Andritz dark theme:

```css
.dark {
--color-background: var(--color-gray-900);
--color-foreground: var(--color-gray-50);
--color-muted: var(--color-gray-800);
--color-muted-foreground: var(--color-gray-400);
--color-secondary: var(--color-gray-800);
/* Surface Hierarchy — "The Void" */
--color-surface: #10141a;
--color-surface-container: #1c2026;
--color-surface-container-low: #181c22;
--color-surface-container-high: #262a31;
--color-surface-container-highest: #31353c;
--color-surface-container-lowest: #0a0e14;

/* Primary (inverted for dark) */
--color-primary: #0075be; /* action containers */
--color-primary-text: #9bcaff; /* text/iconography */

/* Text */
--color-on-surface: #dfe2eb;
--color-on-surface-variant: #c0c7d2;

/* Tertiary (Warning — "caution tape") */
--color-tertiary: #ffb781;

/* Ghost Border — 20% in dark */
--color-outline-variant: #404751;
}
```

## Naming Convention

```
--{category}-{item}-{variant}-{state}
--{scope}-{token}-{variant}-{state}

Examples:
--color-primary # category-item
--color-primary-hover # category-item-state
--button-bg-hover # component-property-state
--space-section-sm # category-semantic-variant
--andritz-blue-600 # primitive color
--color-surface-container # semantic surface
--button-bg # component property
--input-focus-border # component-state
```

## Categories

| Category | Examples |
|----------|----------|
| color | primary, secondary, muted, destructive |
| space | 1, 2, 4, 8, section, component |
| font-size | xs, sm, base, lg, xl |
| radius | sm, default, lg, full |
| shadow | sm, default, lg |
| duration | fast, normal, slow |
| andritz-blue | 900, 700, 600, 500, 300, 200 |
| surface | lowest, low, base, mid, high, highest |
| neutral | 950, 900, 700, 300, 200 |
| space | 2, 4, 6, 8, 12, 16, 20, 32 (8px grid) |
| radius | none (0px), full (9999px) — no others |
| shadow | ambient-light, ambient-dark, glow-primary |
| duration | fast (150ms), normal (200ms), slow (300ms) |

## File Organization

```
tokens/
├── primitives.css # Raw values
├── semantic.css # Purpose aliases
├── components.css # Component tokens
└── index.css # Imports all
├── primitives.css # Andritz blue, surface, neutral scales
├── semantic.css # Surface hierarchy, purpose aliases
├── components.css # Industrial component tokens
└── index.css # Imports all layers
```

Or single file with layer comments:

```css
/* === PRIMITIVES === */
/* === ANDRITZ PRIMITIVES === */
:root { ... }

/* === SEMANTIC === */
/* === SEMANTIC (Light) === */
:root { ... }

/* === COMPONENTS === */
Expand All @@ -183,27 +217,27 @@ Or single file with layer comments:
.dark { ... }
```

## Migration from Flat Tokens
## Migration from Generic Tokens

Before (flat):
Before (generic):
```css
--button-primary-bg: #2563EB;
--button-secondary-bg: #F3F4F6;
--card-radius: 0.5rem;
--border: 1px solid #E5E7EB;
```

After (three-layer):
After (Andritz three-layer):
```css
/* Primitive */
--color-blue-600: #2563EB;
--color-gray-100: #F3F4F6;
--andritz-blue-500: #0075be;

/* Semantic */
--color-primary: var(--color-blue-600);
--color-secondary: var(--color-gray-100);
--color-primary: var(--andritz-blue-500);
--color-border: transparent; /* No-Line Rule */

/* Component */
--button-bg: var(--color-primary);
--button-secondary-bg: var(--color-secondary);
--button-bg: linear-gradient(135deg, var(--color-primary-text), var(--color-primary));
--card-radius: 0px; /* Industrial Precision */
```

## W3C DTCG Alignment
Expand All @@ -213,9 +247,9 @@ Token JSON format (W3C Design Tokens Community Group):
```json
{
"color": {
"blue": {
"600": {
"$value": "#2563EB",
"andritz-blue": {
"500": {
"$value": "#0075be",
"$type": "color"
}
}
Expand Down