Design Systems Architecture
Implements production-grade design systems that provide a unified visual language across web, mobile, and desktop platforms. This skill makes the model architect design token hierarchies, build accessible component libraries with theming support, and enforce cross-platform consistency through typed token adapters.
TL;DR Checklist
- Organize tokens into primitive (atomic) → semantic (role-based) → alias (component-specific) layers
- Type all tokens with TypeScript interfaces — never ship untyped design values
- Map semantic tokens to CSS custom properties for runtime theme switching
- Verify all color pairs meet WCAG 2.2 AA contrast ratios (4.5:1 text, 3:1 large text)
- Include focus-visible styles and skip-nav patterns in every component
- Support prefers-reduced-motion and reduced-transparency for platform accessibility
- Use a single token source mapped to platform-specific adapters (web → CSS vars, RN → JS objects)
- Document components with prop tables, usage guidelines, and explicit do/don't examples
When to Use
Use this skill when:
- Starting a new design system or redesigning an existing one from scratch
- Unifying visual consistency across multiple platforms (web + mobile + desktop)
- Implementing dark mode, brand theming, or user-selectable themes at runtime
- Building a component library consumed by multiple applications
- Auditing an existing UI for accessibility compliance and token architecture quality
- Establishing design token governance rules for a multi-team organization
When NOT to Use
Avoid this skill for:
- Single-page apps with no theming or multi-platform needs — use simple CSS variables instead
- One-off landing pages where design system overhead outweighs benefits
- Backend API architecture — use
api-designfor server-side concerns - Low-level component composition patterns (compound components, render props) — use
component-architecture - General software engineering principles (SOLID, DRY) — use
engineering-principles
Core Workflow
Audit Existing Design — Inventory current colors, typography, spacing, and motion values. Identify duplicates, inconsistencies, and hardcoded magic numbers. Checkpoint: Every visual value should be traceable to a single token source. If two files define the same color differently, that is a design debt item.
Define Primitive Tokens — Create the atomic layer: base colors (hex/rgb), spacing scale (px or rem multiples), font sizes and families, border radius values, z-index tiers, motion duration/duration-easing pairs. Checkpoint: Primitives must be platform-agnostic. Do not include
pxin token names; resolve units at the adapter layer.Define Semantic Tokens — Build the role-based layer that maps primitives to UI concepts:
color.background.primary,color.text.heading,spacing.padding.container,radius.rounded.small. Checkpoint: Each semantic token must resolve to exactly one primitive path. No direct hex values at this level — always reference another token.Define Alias Tokens — Create component-specific tokens that alias semantically:
button.background.primary,card.border.radius,input.focus.ring.color. These allow per-component overrides without breaking the hierarchy. Checkpoint: Alias tokens are the only place where a component can intentionally diverge from semantic defaults. Document why in the token metadata.Map Tokens to Runtime — Generate platform-specific representations:
- Web → CSS custom properties injected into
:rootand theme selectors - React Native → JS constant objects consumed by style props
- Electron/Tauri → Same as web via IPC or embedded stylesheets Checkpoint: The token schema must be serializable to JSON. All platforms derive from the same source of truth.
- Web → CSS custom properties injected into
Build Accessible Component Wrappers — Implement components that consume tokens through a theme provider, enforce focus-visible states, manage keyboard navigation, and expose screen-reader-friendly semantics. Checkpoint: Run automated contrast checks on all token-based color pairs before releasing a component.
Document with Living Examples — Create component stories showing prop variations, usage guidelines with do/don't code examples, and explicit accessibility notes per component.
Implementation Patterns
Pattern 1: Design Token Architecture (Primitive → Semantic → Alias Layers)
Tokens are organized in three layers. Each layer references the one below it. No layer contains hardcoded magic values.
// src/design-system/tokens/primitives.ts
export interface PrimitiveTokens {
color: {
brand: Record<string, string>; // primary, secondary, tertiary
neutral: Record<string, string>; // 0 (white) → 1000 (black)
status: Record<'success' | 'warning' | 'error' | 'info', string>;
semantic: {
bg: Record<string, string>; // surface, overlay, backdrop
text: Record<string, string>; // primary, secondary, inverse
border: Record<string, string>; // default, strong, subtle
};
};
spacing: Record<string, number>; // 4px base unit multipliers
typography: {
fontFamily: Record<string, string>;
fontSize: Record<string, number>; // px values — resolved by adapter
fontWeight: Record<'light' | 'regular' | 'medium' | 'bold', number>;
lineHeight: Record<string, number>;
};
radius: Record<string, number>; // border-radius in px
zIndices: Record<'dropdown' | 'sticky' | 'modal' | 'tooltip', number>;
motion: {
duration: Record<'instant' | 'fast' | 'normal' | 'slow', string>;
easing: Record<'ease' | 'ease-in-out' | 'smooth', string>;
};
}
// src/design-system/tokens/semantic.ts
export interface SemanticTokens extends Partial<PrimitiveTokens> {
color: {
background: {
primary: string; // token path → primitives.color.neutral.0
secondary: string; // token path → primitives.color.neutral.50
elevated: string; // token path → primitives.color.neutral.10
};
text: {
primary: string; // → primitives.color.semantic.text.primary
secondary: string; // → primitives.color.semantic.text.secondary
disabled: string; // → primitives.color.semantic.text.tertiary
inverse: string; // → primitives.color.neutral.0
};
interactive: {
primary: string; // → primitives.color.brand.primary
hover: string; // derived from brand with alpha
active: string; // derived from brand with darker shade
focusRing: string; // → primitives.color.brand.primary (50% opacity)
};
};
spacing: {
xs: string; // → primitives.spacing.1 (4px)
sm: string; // → primitives.spacing.2 (8px)
md: string; // → primitives.spacing.4 (16px)
lg: string; // → primitives.spacing.8 (32px)
xl: string; // → primitives.spacing.12 (48px)
};
typography: {
heading: {
size: string; // → primitives.typography.fontSize.xl
weight: string; // → primitives.typography.fontWeight.bold
lineHeight: string; // → primitives.typography.lineHeight.tight
};
body: {
size: string; // → primitives.typography.fontSize.md
weight: string; // → primitives.typography.fontWeight.regular
lineHeight: string; // → primitives.typography.lineHeight.relaxed
};
};
}
// src/design-system/tokens/aliases.ts — Component-level token aliases
export interface AliasTokens {
button: {
background: string; // → semantic.color.interactive.primary
backgroundHover: string;
backgroundDisabled: string;
color: string; // → semantic.color.text.inverse
paddingX: string; // → semantic.spacing.md
paddingY: string; // → semantic.spacing.sm
borderRadius: string; // → primitives.radius.rounded
};
card: {
background: string; // → semantic.color.background.elevated
borderColor: string; // → semantic.color.border.subtle
borderRadius: string; // → primitives.radius.lg
shadow: string; // defined as CSS box-shadow token
};
input: {
background: string; // → semantic.color.background.primary
borderColor: string; // → semantic.color.border.default
focusBorderColor: string; // → semantic.color.interactive.focusRing
errorBorderColor: string; // → semantic.color.status.error
placeholderColor: string; // → semantic.color.text.secondary
};
}
Pattern 2: CSS Custom Properties Theming System
Tokens are exposed as CSS custom properties. A theme class on a parent element overrides the property values, enabling runtime switching without JS re-renders of every component.
/* src/design-system/styles/tokens.css */
/* Base theme (light) — defines all custom properties from tokens */
:root {
/* Primitive tokens as CSS custom properties */
--ds-color-brand-primary: #2563eb;
--ds-color-brand-secondary: #7c3aed;
--ds-color-neutral-0: #ffffff;
--ds-color-neutral-100: #f8fafc;
--ds-color-neutral-200: #e2e8f0;
--ds-color-neutral-600: #475569;
--ds-color-neutral-900: #0f172a;
/* Spacing — in rem for fluid scaling */
--ds-spacing-xs: 0.25rem; /* 4px */
--ds-spacing-sm: 0.5rem; /* 8px */
--ds-spacing-md: 1rem; /* 16px */
--ds-spacing-lg: 2rem; /* 32px */
/* Typography */
--ds-font-family-sans: 'Inter', system-ui, -apple-system, sans-serif;
--ds-font-size-xs: 0.75rem;
--ds-font-size-sm: 0.875rem;
--ds-font-size-base: 1rem;
--ds-font-size-lg: 1.125rem;
--ds-font-size-xl: 1.25rem;
--ds-font-weight-regular: 400;
--ds-font-weight-bold: 700;
/* Semantic layer — references primitives by name */
--ds-color-bg-primary: var(--ds-color-neutral-0);
--ds-color-bg-elevated: var(--ds-color-neutral-100);
--ds-color-text-primary: var(--ds-color-neutral-900);
--ds-color-text-secondary: var(--ds-color-neutral-600);
--ds-color-border-default: var(--ds-color-neutral-200);
/* Alias tokens — component-level overrides */
--ds-button-bg: var(--ds-color-brand-primary);
--ds-button-bg-hover: color-mix(in srgb, var(--ds-color-brand-primary) 85%, black);
--ds-button-color: var(--ds-color-neutral-0);
}
/* Dark theme — only override what changes */
[data-theme="dark"] {
--ds-color-neutral-0: #0f172a;
--ds-color-neutral-100: #1e293b;
--ds-color-neutral-600: #94a3b8;
--ds-color-neutral-900: #f8fafc;
--ds-color-bg-primary: var(--ds-color-neutral-0);
--ds-color-bg-elevated: var(--ds-color-neutral-100);
--ds-color-text-primary: var(--ds-color-neutral-900);
--ds-color-text-secondary: var(--ds-color-neutral-600);
--ds-button-bg-hover: color-mix(in srgb, var(--ds-color-brand-primary) 85%, white);
}
/* High-contrast theme for accessibility — meets WCAG AAA */
[data-theme="high-contrast"] {
--ds-color-text-primary: #000000;
--ds-color-bg-primary: #ffffff;
--ds-color-border-default: #000000;
--ds-spacing-focus-ring: 3px;
}
/* Reduced motion — disables all non-essential animations */
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}
Pattern 3: React Theme Provider with Typed Token Consumption
A React context provides the token map. Components consume tokens via a typed hook, ensuring type safety and tree-shakeability.
// src/design-system/theme/ThemeContext.tsx
import { createContext, useContext, useCallback } from 'react';
import type { SemanticTokens, AliasTokens } from '../tokens/types';
export interface ThemeState {
tokens: SemanticTokens;
aliases: AliasTokens;
direction: 'ltr' | 'rtl';
}
// The context carries the full token map — never raw hex values
const ThemeContext = createContext<ThemeState | null>(null);
interface ThemeProviderProps {
children: React.ReactNode;
tokens: SemanticTokens;
aliases: AliasTokens;
direction?: 'ltr' | 'rtl';
}
export function ThemeProvider({
children,
tokens,
aliases,
direction = 'ltr',
}: ThemeProviderProps): React.ReactElement {
const state = useMemo(
() => ({ tokens, aliases, direction }),
[tokens, aliases, direction],
);
return (
<ThemeContext.Provider value={state}>
{children}
</ThemeContext.Provider>
);
}
export function useTheme(): ThemeState {
const context = useContext(ThemeContext);
if (context === null) {
throw new Error('useTheme must be used within a ThemeProvider');
}
return context;
}
// Typed accessors for alias tokens — prevents direct primitive consumption in components
export function useToken<K extends keyof AliasTokens>(
category: K,
): Required<AliasTokens[K]> {
const { aliases } = useTheme();
return aliases[category] as Required<AliasTokens[K]>;
}
// Generic hook for semantic token access with CSS variable generation
export function useCSSVariable(tokenPath: string): string {
const { tokens } = useTheme();
// Resolve the token path to a CSS custom property name
return `var(--ds-${tokenPath.replace(/\./g, '-')})`;
}
// src/design-system/components/Button.tsx — Example component consuming tokens
import { useTheme, useToken } from '../theme/ThemeContext';
export interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
variant?: 'primary' | 'secondary' | 'ghost';
size?: 'sm' | 'md' | 'lg';
disabled?: boolean;
}
export function Button({
children,
variant = 'primary',
size = 'md',
disabled = false,
className = '',
...props
}: ButtonProps): React.ReactElement {
const { tokens } = useTheme();
const buttonTokens = useToken('button');
// Compute styles from tokens — never hardcode colors or spacing in component logic
const paddingY = size === 'sm' ? tokens.spacing.sm : tokens.spacing.md;
const paddingX = size === 'lg' ? tokens.spacing.lg : tokens.spacing.md;
const baseStyles: React.CSSProperties = {
fontFamily: tokens.typography.fontFamily.sans,
fontWeight: tokens.typography.fontWeight.bold,
fontSize: tokens.typography.fontSize.base,
lineHeight: tokens.typography.lineHeight.normal,
padding: `${paddingY} ${paddingX}`,
borderRadius: buttonTokens.borderRadius,
cursor: disabled ? 'not-allowed' : 'pointer',
border: variant === 'ghost' ? 'none' : '1px solid transparent',
transition: `background ${tokens.motion.duration.normal} ${tokens.motion.easing.smooth}`,
// Focus management — visible focus ring for keyboard navigation
':focus-visible': {
outline: '2px solid var(--ds-color-interactive-focusRing)',
outlineOffset: '2px',
},
};
const variantStyles: Record<ButtonProps['variant'], React.CSSProperties> = {
primary: {
background: buttonTokens.background,
color: buttonTokens.color,
},
secondary: {
background: tokens.color.background.secondary,
color: tokens.color.text.primary,
borderColor: tokens.color.border.default,
},
ghost: {
background: 'transparent',
color: tokens.color.text.primary,
},
};
const disabledStyles: React.CSSProperties = disabled
? { opacity: 0.5, cursor: 'not-allowed' }
: {};
return (
<button
className={className}
disabled={disabled}
style={{ ...baseStyles, ...variantStyles[variant], ...disabledStyles }}
{...props}
>
{children}
</button>
);
}
Pattern 4: Accessibility Utility Functions
Accessibility is baked into the design system through utility functions that validate tokens and provide accessible component primitives.
// src/design-system/a11y/contrast.ts — WCAG 2.2 AA contrast ratio checker
/**
* Convert hex color to relative luminance per WCAG 2.2 specification.
* Uses sRGB linearization before luminance calculation.
*/
export function hexToRgb(hex: string): { r: number; g: number; b: number } {
const cleaned = hex.replace('#', '');
if (cleaned.length === 3) {
return {
r: parseInt(cleaned[0] + cleaned[0], 16),
g: parseInt(cleaned[1] + cleaned[1], 16),
b: parseInt(cleaned[2] + cleaned[2], 16),
};
}
if (cleaned.length !== 6) {
throw new Error(`Invalid hex color: ${hex}`);
}
return {
r: parseInt(cleaned.substring(0, 2), 16),
g: parseInt(cleaned.substring(2, 4), 16),
b: parseInt(cleaned.substring(4, 6), 16),
};
}
/**
* Calculate relative luminance per WCAG 2.2 formula.
* Returns a value between 0 (black) and 1 (white).
*/
export function relativeLuminance({ r, g, b }: { r: number; g: number; b: number }): number {
const [rs, gs, bs] = [r, g, b].map((c) => {
const srgb = c / 255;
return srgb <= 0.03928 ? srgb / 12.92 : Math.pow((srgb + 0.055) / 1.055, 2.4);
});
return 0.2126 * rs + 0.7152 * gs + 0.0722 * bs;
}
/**
* Calculate contrast ratio between two colors per WCAG 2.2.
* Returns ratio as a number (e.g., 4.5 = meets AA for normal text).
*/
export function contrastRatio(color1: string, color2: string): number {
const lum1 = relativeLuminance(hexToRgb(color1));
const lum2 = relativeLuminance(hexToRgb(color2));
const lighter = Math.max(lum1, lum2);
const darker = Math.min(lum1, lum2);
return (lighter + 0.05) / (darker + 0.05);
}
/**
* Validate that a foreground/background color pair meets WCAG 2.2 AA.
* Throws an error if the contrast ratio is insufficient.
*/
export function assertContrast(
fg: string,
bg: string,
level: 'AA' | 'AAA' = 'AA',
context?: string,
): void {
const ratio = contrastRatio(fg, bg);
const minRatio = level === 'AA' ? 4.5 : 7;
if (ratio < minRatio) {
const msg = `Contrast ratio ${ratio.toFixed(2)}:1 between "${fg}" and "${bg}" ` +
`fails WCAG 2.2 ${level} (minimum ${minRatio}:1)`;
throw new Error(context ? `${msg} (${context})` : msg);
}
}
/**
* Validate a complete theme's color pairs for accessibility compliance.
*/
export function validateThemeColors(semanticTokens: SemanticTokens): void {
const checks: Array<{ fg: string; bg: string }> = [
{ fg: semanticTokens.color.text.primary, bg: semanticTokens.color.background.primary },
{ fg: semanticTokens.color.text.secondary, bg: semanticTokens.color.background.primary },
{ fg: semanticTokens.color.interactive.primary, bg: semanticTokens.color.background.primary },
{ fg: semanticTokens.color.text.inverse, bg: semanticTokens.color.interactive.primary },
];
for (const { fg, bg } of checks) {
assertContrast(fg, bg, 'AA', `color pair ${fg} / ${bg}`);
}
}
// src/design-system/a11y/focusTrap.ts — Focus management for modals and overlays
/**
* Programmatically trap focus within a container element.
* Used by modal, dialog, and drawer components to keep keyboard
* navigation contained when the overlay is open.
*/
export class FocusTrap {
private container: HTMLElement;
private previousActiveElement: HTMLElement | null = null;
private keydownHandler: (e: KeyboardEvent) => void;
constructor(container: HTMLElement) {
this.container = container;
this.keydownHandler = this.handleKeydown.bind(this);
}
/** Activate the focus trap — call when overlay becomes visible */
activate(): void {
this.previousActiveElement = document.activeElement as HTMLElement;
// Find the first focusable element to move focus into
const focusable = this.getFocusableElements();
if (focusable.length > 0) {
focusable[0].focus();
}
document.addEventListener('keydown', this.keydownHandler);
}
/** Deactivate — call when overlay closes, restore previous focus */
deactivate(): void {
document.removeEventListener('keydown', this.keydownHandler);
if (this.previousActiveElement instanceof HTMLElement) {
this.previousActiveElement.focus();
}
}
/** Tab key handler that cycles focus within the container */
private handleKeydown(e: KeyboardEvent): void {
if (e.key !== 'Tab') return;
const focusable = this.getFocusableElements();
if (focusable.length === 0) return;
const firstElement = focusable[0];
const lastElement = focusable[focusable.length - 1];
if (e.shiftKey && document.activeElement === firstElement) {
e.preventDefault();
lastElement.focus();
} else if (!e.shiftKey && document.activeElement === lastElement) {
e.preventDefault();
firstElement.focus();
}
}
/** Query all focusable elements within the container */
private getFocusableElements(): HTMLElement[] {
const selectors = [
'a[href]',
'button:not([disabled])',
'input:not([disabled])',
'select:not([disabled])',
'textarea:not([disabled])',
'[tabindex]:not([tabindex="-1"])',
].join(', ');
return Array.from(this.container.querySelectorAll<HTMLElement>(selectors));
}
}
Pattern 5: Cross-Platform Token Adapter
The same token source maps to different runtime representations for each platform. This ensures one design language across all platforms.
// src/design-system/adapters/web-token-adapter.ts — Web (CSS Custom Properties)
interface TokenMap {
[cssVar: string]: string | number;
}
/**
* Convert the token object into a flat CSS custom property map.
* Dot paths become hyphenated CSS variables: "color.brand.primary" → "--ds-color-brand-primary"
*/
export function flattenToCSSVariables(
tokens: Record<string, unknown>,
prefix = '--ds',
): TokenMap {
const result: TokenMap = {};
function walk(obj: Record<string, unknown>, path: string[]): void {
for (const [key, value] of Object.entries(obj)) {
const currentPath = [...path, key];
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
walk(value as Record<string, unknown>, currentPath);
} else {
const cssVar = `${prefix}-${currentPath.join('-')}`;
result[cssVar] = String(value);
}
}
}
walk(tokens, []);
return result;
}
/**
* Generate a CSS stylesheet string from the token map.
* Supports injecting into multiple themes via data-theme attribute selectors.
*/
export function generateTokenStylesheet(
tokens: TokenMap,
themeName: string = 'light',
): string {
const selector = themeName === 'light' ? ':root' : `[data-theme="${themeName}"]`;
const declarations = Object.entries(tokens)
.map(([key, value]) => ` ${key}: ${value};`)
.join('\n');
return `/* Generated design tokens — ${themeName} theme */
${selector} {
${declarations}
}`;
}
// src/design-system/adapters/mobile-token-adapter.ts — React Native / JS platform
interface MobileTokenMap {
[key: string]: string | number;
}
/**
* Convert the token object into a JS object consumable by React Native style props.
* Resolves CSS unit tokens (rem) to platform-specific values (dp for Android, pt for iOS).
*/
export function flattenToJSObject(
tokens: Record<string, unknown>,
pxMultiplier = 1, // Platform-specific conversion factor
): MobileTokenMap {
const result: MobileTokenMap = {};
function walk(obj: Record<string, unknown>, path: string[]): void {
for (const [key, value] of Object.entries(obj)) {
const currentPath = [...path, key];
const flatKey = currentPath.join('.');
if (typeof value === 'object' && value !== null && !Array.isArray(value)) {
walk(value as Record<string, unknown>, currentPath);
} else if (typeof value === 'number') {
// Resolve spacing and sizing tokens to platform units
result[flatKey] = value * pxMultiplier;
} else {
result[flatKey] = String(value);
}
}
}
walk(tokens, []);
return result;
}
/**
* Create a React Native theme object from tokens.
* Returns an object ready to spread into style() calls.
*/
export function createNativeTheme(
jsTokens: MobileTokenMap,
): {
colors: Record<string, string>;
spacing: Record<string, number>;
typography: Record<string, string | number>;
} {
const colors: Record<string, string> = {};
const spacing: Record<string, number> = {};
const typography: Record<string, string | number> = {};
for (const [key, value] of Object.entries(jsTokens)) {
if (key.startsWith('color.')) {
colors[key.replace('color.', '')] = String(value);
} else if (key.startsWith('spacing.')) {
spacing[key.replace('spacing.', '')] = Number(value);
} else if (key.startsWith('typography.')) {
typography[key.replace('typography.', '')] = value;
}
}
return { colors, spacing, typography };
}
Constraints
MUST DO
- Organize tokens in the three-layer hierarchy: primitive → semantic → alias. Never skip a layer.
- Type all tokens with TypeScript interfaces — untyped token values cause runtime inconsistencies.
- Map every semantic token to a CSS custom property for runtime theme switching without component re-renders.
- Validate contrast ratios for every color pair using
assertContrastbefore releasing components. - Include
:focus-visiblestyles on all interactive elements — never rely on default browser outlines alone. - Support
prefers-reduced-motionby providing a CSS media query that disables non-essential transitions. - Use a single token source of truth; generate platform-specific representations via adapters, never duplicate tokens per platform.
- Document every component with prop tables, usage examples, and explicit do/don't accessibility guidance.
- Use
data-themeattributes on root elements for theme switching — do not rely on JavaScript-only state for visual appearance.
MUST NOT DO
- Hardcode hex values inside components — they must always come from token consumption via the theme provider.
- Use CSS-in-JS solution-specific tokens (e.g., emotion/StyledComponents template literals) as the primary token delivery mechanism — CSS custom properties are the universal layer.
- Place hardcoded colors in
useThemereturn values — the hook returns token references, not resolved hex strings. - Skip focus management on modals, dialogs, or drawers — always implement a
FocusTrap. - Use
outline: nonewithout providing an equivalent visible focus indicator. - Define different token sets for each platform — all platforms derive from one source through adapters.
- Omit
prefers-reduced-motionmedia query handling — it is not optional for accessibility compliance. - Name tokens after visual appearance alone (e.g.,
blueButtonBg) — use functional names (button.background.primary).
Output Template
When implementing or auditing a design system, produce:
- Token Hierarchy Map — A structured listing of primitive → semantic → alias token paths with their resolved values and the platform representations generated.
- CSS Custom Property Sheet — The complete
:rootand[data-theme="dark"]CSS variable declarations. - Theme Provider Component — Typed React context provider with hook accessors, including error handling for missing context.
- Accessibility Validation Report — Contrast ratio results for all foreground/background pairs, focus management patterns used, and
prefers-reduced-motioncoverage. - Platform Adapter Configurations — Web CSS output, React Native JS object output, with platform-specific unit conversions documented.
- Component Story Examples — At least one do/don't usage pair showing correct token consumption and accessibility attributes.
Related Skills
| Skill | Purpose |
|---|---|
component-architecture |
Compound components, headless UI patterns — how to structure the components your design system provides |
api-design |
Backend API contract design — pairs with design system when building full-stack product interfaces |
engineering-principles |
SOLID, DRY, separation of concerns — guides the architecture of the design system codebase itself |
Live References
Authoritative documentation links for this skill's domain. The model follows markdown links at load time to resolve external references and inline content.