Files
gh-jamesrochabrun-skills-al…/skills/frontend-designer/references/design_tokens.md
2025-11-29 18:48:58 +08:00

12 KiB

Design Tokens Reference

Complete guide to implementing and using design tokens in your design system.

What Are Design Tokens?

Design tokens are the visual design atoms of your design system — specifically, they are named entities that store visual design attributes. They're used in place of hard-coded values to maintain a scalable and consistent visual system.

Benefits

Consistency

  • Single source of truth for design values
  • Ensures brand consistency across platforms
  • Easy to maintain and update

Scalability

  • Change values in one place, update everywhere
  • Support multiple themes (light/dark)
  • Platform-agnostic (web, iOS, Android)

Developer-Designer Communication

  • Shared vocabulary between teams
  • Design decisions are codified
  • Reduces ambiguity

Token Categories

1. Color Tokens

:root {
  /* Brand Colors */
  --color-primary: #0066FF;
  --color-primary-hover: #0052CC;
  --color-primary-active: #003D99;
  --color-primary-subtle: #E6F0FF;

  --color-secondary: #6B7280;
  --color-secondary-hover: #4B5563;

  /* Semantic Colors */
  --color-success: #10B981;
  --color-warning: #F59E0B;
  --color-error: #EF4444;
  --color-info: #3B82F6;

  /* Neutral Palette */
  --color-white: #FFFFFF;
  --color-black: #000000;
  --color-gray-50: #F9FAFB;
  --color-gray-100: #F3F4F6;
  /* ... through gray-900 */

  /* Surface Colors */
  --color-surface: var(--color-white);
  --color-background: var(--color-white);

  /* Text Colors */
  --color-text: var(--color-gray-900);
  --color-text-secondary: var(--color-gray-600);
  --color-text-tertiary: var(--color-gray-400);

  /* Border Colors */
  --color-border: var(--color-gray-200);
  --color-border-hover: var(--color-gray-300);

  /* Focus */
  --color-focus: var(--color-primary);
}

Naming Convention:

--color-{category}-{variant}-{state}

Examples:
--color-primary              (base brand color)
--color-primary-hover        (interactive state)
--color-success-subtle       (background usage)
--color-text-secondary       (content hierarchy)

2. Typography Tokens

:root {
  /* Font Families */
  --font-base: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  --font-heading: var(--font-base);
  --font-mono: "SF Mono", Monaco, "Cascadia Code", monospace;

  /* Font Sizes - Fluid Typography */
  --text-xs: clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem);
  --text-sm: clamp(0.875rem, 0.825rem + 0.25vw, 1rem);
  --text-base: clamp(1rem, 0.95rem + 0.25vw, 1.125rem);
  --text-lg: clamp(1.125rem, 1.05rem + 0.375vw, 1.25rem);
  --text-xl: clamp(1.25rem, 1.15rem + 0.5vw, 1.5rem);
  --text-2xl: clamp(1.5rem, 1.35rem + 0.75vw, 1.875rem);
  --text-3xl: clamp(1.875rem, 1.65rem + 1.125vw, 2.25rem);
  --text-4xl: clamp(2.25rem, 1.95rem + 1.5vw, 3rem);
  --text-5xl: clamp(3rem, 2.55rem + 2.25vw, 3.75rem);

  /* Font Weights */
  --font-light: 300;
  --font-normal: 400;
  --font-medium: 500;
  --font-semibold: 600;
  --font-bold: 700;

  /* Line Heights */
  --leading-tight: 1.25;
  --leading-normal: 1.5;
  --leading-relaxed: 1.625;
  --leading-loose: 2;

  /* Letter Spacing */
  --tracking-tight: -0.025em;
  --tracking-normal: 0;
  --tracking-wide: 0.025em;
}

Usage:

.heading-1 {
  font-family: var(--font-heading);
  font-size: var(--text-4xl);
  font-weight: var(--font-bold);
  line-height: var(--leading-tight);
  letter-spacing: var(--tracking-tight);
}

.body-text {
  font-family: var(--font-base);
  font-size: var(--text-base);
  font-weight: var(--font-normal);
  line-height: var(--leading-normal);
}

3. Spacing Tokens

:root {
  /* Spacing Scale (4px base) */
  --space-0: 0;
  --space-1: 0.25rem;    /* 4px */
  --space-2: 0.5rem;     /* 8px */
  --space-3: 0.75rem;    /* 12px */
  --space-4: 1rem;       /* 16px */
  --space-5: 1.25rem;    /* 20px */
  --space-6: 1.5rem;     /* 24px */
  --space-8: 2rem;       /* 32px */
  --space-10: 2.5rem;    /* 40px */
  --space-12: 3rem;      /* 48px */
  --space-16: 4rem;      /* 64px */
  --space-20: 5rem;      /* 80px */
  --space-24: 6rem;      /* 96px */
}

Usage:

.card {
  padding: var(--space-4);
  margin-bottom: var(--space-6);
  gap: var(--space-3);
}

.section {
  padding-block: var(--space-12);
}

4. Shadow Tokens

:root {
  --shadow-xs: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
  --shadow-sm: 0 1px 3px 0 rgba(0, 0, 0, 0.1);
  --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
  --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
  --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1);
  --shadow-2xl: 0 25px 50px -12px rgba(0, 0, 0, 0.25);

  /* Special Shadows */
  --shadow-inner: inset 0 2px 4px 0 rgba(0, 0, 0, 0.06);
  --shadow-focus: 0 0 0 3px rgba(0, 102, 255, 0.5);
}

Usage:

.card {
  box-shadow: var(--shadow-md);
}

.card:hover {
  box-shadow: var(--shadow-lg);
}

button:focus-visible {
  box-shadow: var(--shadow-focus);
}

5. Border Tokens

:root {
  /* Border Radius */
  --radius-sm: 0.125rem;   /* 2px */
  --radius-md: 0.375rem;   /* 6px */
  --radius-lg: 0.5rem;     /* 8px */
  --radius-xl: 0.75rem;    /* 12px */
  --radius-2xl: 1rem;      /* 16px */
  --radius-full: 9999px;   /* Pills/circles */

  /* Border Widths */
  --border-1: 1px;
  --border-2: 2px;
  --border-4: 4px;
}

Usage:

.button {
  border-radius: var(--radius-md);
  border: var(--border-1) solid var(--color-border);
}

.avatar {
  border-radius: var(--radius-full);
}

6. Z-Index Tokens

:root {
  /* Layer Management */
  --z-dropdown: 1000;
  --z-sticky: 1020;
  --z-fixed: 1030;
  --z-modal-backdrop: 1040;
  --z-modal: 1050;
  --z-popover: 1060;
  --z-tooltip: 1070;
}

Usage:

.modal-backdrop {
  z-index: var(--z-modal-backdrop);
}

.modal {
  z-index: var(--z-modal);
}

7. Animation/Transition Tokens

:root {
  /* Duration */
  --duration-instant: 0ms;
  --duration-fast: 150ms;
  --duration-base: 250ms;
  --duration-slow: 350ms;
  --duration-slower: 500ms;

  /* Easing */
  --ease-linear: linear;
  --ease-in: cubic-bezier(0.4, 0, 1, 1);
  --ease-out: cubic-bezier(0, 0, 0.2, 1);
  --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
  --ease-bounce: cubic-bezier(0.68, -0.55, 0.265, 1.55);
}

Usage:

.button {
  transition: all var(--duration-base) var(--ease-out);
}

.modal {
  animation: slideIn var(--duration-slow) var(--ease-out);
}

Semantic vs Reference Tokens

Reference Tokens (Raw Values)

:root {
  --blue-500: #0066FF;
  --gray-100: #F3F4F6;
  --spacing-4: 1rem;
}

Semantic Tokens (Meaningful Names)

:root {
  --color-primary: var(--blue-500);
  --color-surface: var(--gray-100);
  --button-padding: var(--spacing-4);
}

Always use semantic tokens in components:

/* ❌ Don't */
.button {
  background: var(--blue-500);
  padding: var(--spacing-4);
}

/* ✅ Do */
.button {
  background: var(--color-primary);
  padding: var(--button-padding);
}

Theming with Tokens

Light/Dark Mode

:root {
  /* Light theme (default) */
  --color-surface: #FFFFFF;
  --color-text: #111827;
  --color-border: #E5E7EB;
}

@media (prefers-color-scheme: dark) {
  :root {
    --color-surface: #1F2937;
    --color-text: #F9FAFB;
    --color-border: #4B5563;
  }
}

/* Or class-based theming */
[data-theme="dark"] {
  --color-surface: #1F2937;
  --color-text: #F9FAFB;
  --color-border: #4B5563;
}

Brand Theming

:root {
  --color-primary: var(--brand-blue);
}

[data-brand="tech"] {
  --brand-blue: #0066FF;
}

[data-brand="health"] {
  --brand-blue: #10B981;
}

[data-brand="finance"] {
  --brand-blue: #6366F1;
}

Component-Specific Tokens

:root {
  /* Button */
  --button-padding-sm: var(--space-2) var(--space-3);
  --button-padding-md: var(--space-3) var(--space-4);
  --button-padding-lg: var(--space-4) var(--space-6);
  --button-radius: var(--radius-md);
  --button-font-weight: var(--font-medium);

  /* Input */
  --input-height-sm: 36px;
  --input-height-md: 44px;
  --input-height-lg: 52px;
  --input-border-color: var(--color-border);
  --input-focus-color: var(--color-primary);

  /* Card */
  --card-padding: var(--space-6);
  --card-radius: var(--radius-lg);
  --card-shadow: var(--shadow-md);
}

Platform-Specific Tokens

CSS Custom Properties (Web)

:root {
  --color-primary: #0066FF;
}

.button {
  background: var(--color-primary);
}

JSON (React Native, iOS, Android)

{
  "color": {
    "primary": "#0066FF",
    "surface": "#FFFFFF",
    "text": "#111827"
  },
  "spacing": {
    "4": 16,
    "6": 24,
    "8": 32
  }
}

JavaScript/TypeScript

export const tokens = {
  color: {
    primary: '#0066FF',
    surface: '#FFFFFF',
    text: '#111827',
  },
  spacing: {
    4: '1rem',
    6: '1.5rem',
    8: '2rem',
  },
} as const;

// Usage
const Button = styled.button`
  background: ${tokens.color.primary};
  padding: ${tokens.spacing.4};
`;

Best Practices

Naming Conventions

Do:

  • Use descriptive, semantic names
  • Follow consistent patterns
  • Group related tokens
/* ✅ Good */
--color-primary
--color-primary-hover
--color-primary-subtle
--button-padding-md
--shadow-card

Don't:

  • Use arbitrary or cryptic names
  • Mix naming conventions
  • Use values in names
/* ❌ Bad */
--blue
--primary-color-hover-state
--padding16px
--btn-pad

Organization

Group tokens by category:

tokens/
├── colors.css
├── typography.css
├── spacing.css
├── shadows.css
├── borders.css
├── zindex.css
└── index.css (imports all)

Documentation

Document token usage:

/**
 * Primary brand color
 * Used for: primary buttons, links, focus states
 * Contrast ratio: 4.6:1 (WCAG AA compliant)
 */
--color-primary: #0066FF;

Accessibility

Ensure proper contrast:

:root {
  --color-primary: #0066FF;
  --color-text-on-primary: #FFFFFF;
  /* Contrast ratio: 4.5:1 ✅ */
}

Performance

Use CSS variables efficiently:

/* ✅ Define once, use everywhere */
:root {
  --color-primary: #0066FF;
}

/* ❌ Don't redefine in every selector */
.button { --color-primary: #0066FF; }
.link { --color-primary: #0066FF; }

Migration Strategy

Step 1: Audit Current Values

# Find all color values
grep -r "#[0-9A-Fa-f]\{6\}" src/

# Find all spacing values
grep -r "padding:\|margin:" src/

Step 2: Create Token Definitions

:root {
  /* Extract unique values */
  --color-primary: #0066FF;
  --space-4: 1rem;
}

Step 3: Replace Hard-Coded Values

/* Before */
.button {
  background: #0066FF;
  padding: 1rem;
}

/* After */
.button {
  background: var(--color-primary);
  padding: var(--space-4);
}

Step 4: Test & Validate

  • Visual regression testing
  • Accessibility testing
  • Cross-browser testing
  • Dark mode verification

Tools

Design Token Tools:

  • Style Dictionary (transforms tokens to multiple formats)
  • Theo (Salesforce's token transformer)
  • Design Tokens CLI

Browser DevTools:

  • Chrome: Inspect computed custom properties
  • Firefox: CSS Variables viewer

Example Script:

// Extract all CSS custom properties
const properties = Array.from(document.styleSheets)
  .flatMap(sheet => Array.from(sheet.cssRules))
  .filter(rule => rule.style)
  .flatMap(rule => Array.from(rule.style))
  .filter(prop => prop.startsWith('--'));

console.log([...new Set(properties)]);

Resources


"Design tokens are the translation layer between design decisions and code."