design-system
Design system architecture: design tokens (color, spacing, typography, radius), component library layers (Primitive → Composite → Pattern), theming with CSS Custom Properties and Tailwind, Storybook documentation, and dark mode. The foundation for consistent UI across an entire product.
Best use case
design-system is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Design system architecture: design tokens (color, spacing, typography, radius), component library layers (Primitive → Composite → Pattern), theming with CSS Custom Properties and Tailwind, Storybook documentation, and dark mode. The foundation for consistent UI across an entire product.
Teams using design-system should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/design-system/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How design-system Compares
| Feature / Agent | design-system | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Design system architecture: design tokens (color, spacing, typography, radius), component library layers (Primitive → Composite → Pattern), theming with CSS Custom Properties and Tailwind, Storybook documentation, and dark mode. The foundation for consistent UI across an entire product.
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Design System Skill
## When to Activate
- Starting a new product UI from scratch
- UI feels inconsistent across pages (colors, spacing, typography vary)
- Multiple developers building UI components independently
- Setting up dark mode or multiple themes
- Building a component library
- Documenting components for a team
- Migrating hardcoded color or spacing values to a token-based system that supports theming
- Structuring components across Primitive, Composite, and Pattern layers to avoid circular dependencies
---
## Layer Architecture
```
Tokens → Raw values (colors, spacing scale, radius, shadows)
Semantic Tokens → Named by purpose (--color-surface, --color-brand-primary)
Primitives → Unstyled, accessible base components (Button, Input, Dialog)
Composites → Styled, opinionated components (SearchBar, UserCard)
Patterns → Full UI sections (EmptyState, DataTable, PageHeader)
```
Each layer only imports from the layer below it. Never skip layers.
---
## Design Tokens
### CSS Custom Properties (recommended — works with any framework)
```css
/* tokens/colors.css */
:root {
/* Palette — raw values, not used directly in components */
--blue-50: #eff6ff;
--blue-100: #dbeafe;
--blue-500: #3b82f6;
--blue-600: #2563eb;
--blue-700: #1d4ed8;
--gray-50: #f9fafb;
--gray-100: #f3f4f6;
--gray-200: #e5e7eb;
--gray-500: #6b7280;
--gray-700: #374151;
--gray-900: #111827;
--red-500: #ef4444;
--green-500: #22c55e;
--yellow-500: #eab308;
/* Semantic tokens — used in components */
--color-brand: var(--blue-600);
--color-brand-hover: var(--blue-700);
--color-brand-subtle: var(--blue-50);
--color-surface: #ffffff;
--color-surface-raised: var(--gray-50);
--color-surface-overlay: var(--gray-100);
--color-text-primary: var(--gray-900);
--color-text-secondary: var(--gray-500);
--color-text-disabled: var(--gray-200);
--color-text-inverse: #ffffff;
--color-text-brand: var(--blue-600);
--color-border: var(--gray-200);
--color-border-strong: var(--gray-500);
--color-border-brand: var(--blue-500);
--color-feedback-error: var(--red-500);
--color-feedback-success: var(--green-500);
--color-feedback-warning: var(--yellow-500);
--color-feedback-info: var(--blue-500);
--color-feedback-error-subtle: #fef2f2;
--color-feedback-success-subtle: #f0fdf4;
}
/* Dark mode — swap semantic tokens only */
[data-theme="dark"] {
--color-surface: #0f172a;
--color-surface-raised: #1e293b;
--color-surface-overlay: #334155;
--color-text-primary: #f8fafc;
--color-text-secondary: #94a3b8;
--color-text-disabled: #475569;
--color-border: #334155;
--color-border-strong: #64748b;
}
```
```css
/* tokens/spacing.css */
:root {
--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 */
/* Semantic spacing */
--spacing-component-xs: var(--space-2);
--spacing-component-sm: var(--space-3);
--spacing-component-md: var(--space-4);
--spacing-component-lg: var(--space-6);
--spacing-section: var(--space-12);
--spacing-page: var(--space-16);
}
```
```css
/* tokens/typography.css */
:root {
--font-sans: 'Inter', system-ui, -apple-system, sans-serif;
--font-mono: 'JetBrains Mono', 'Fira Code', monospace;
--text-xs: 0.75rem; /* 12px */
--text-sm: 0.875rem; /* 14px */
--text-base: 1rem; /* 16px */
--text-lg: 1.125rem; /* 18px */
--text-xl: 1.25rem; /* 20px */
--text-2xl: 1.5rem; /* 24px */
--text-3xl: 1.875rem; /* 30px */
--text-4xl: 2.25rem; /* 36px */
--leading-tight: 1.25;
--leading-snug: 1.375;
--leading-normal: 1.5;
--leading-relaxed: 1.625;
--font-normal: 400;
--font-medium: 500;
--font-semibold: 600;
--font-bold: 700;
}
```
```css
/* tokens/shape.css */
:root {
--radius-sm: 0.25rem; /* 4px — tags, badges */
--radius-md: 0.375rem; /* 6px — buttons, inputs */
--radius-lg: 0.5rem; /* 8px — cards */
--radius-xl: 0.75rem; /* 12px — modals, panels */
--radius-full: 9999px; /* pills */
--shadow-sm: 0 1px 2px 0 rgb(0 0 0 / 0.05);
--shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1);
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1);
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1);
}
```
---
## Tailwind Theme Integration
```typescript
// tailwind.config.ts
import type { Config } from 'tailwindcss';
export default {
content: ['./src/**/*.{ts,tsx}'],
darkMode: ['selector', '[data-theme="dark"]'],
theme: {
extend: {
colors: {
brand: {
DEFAULT: 'var(--color-brand)',
hover: 'var(--color-brand-hover)',
subtle: 'var(--color-brand-subtle)',
},
surface: {
DEFAULT: 'var(--color-surface)',
raised: 'var(--color-surface-raised)',
overlay: 'var(--color-surface-overlay)',
},
text: {
primary: 'var(--color-text-primary)',
secondary: 'var(--color-text-secondary)',
disabled: 'var(--color-text-disabled)',
inverse: 'var(--color-text-inverse)',
brand: 'var(--color-text-brand)',
},
border: {
DEFAULT: 'var(--color-border)',
strong: 'var(--color-border-strong)',
brand: 'var(--color-border-brand)',
},
error: 'var(--color-feedback-error)',
success: 'var(--color-feedback-success)',
warning: 'var(--color-feedback-warning)',
},
fontFamily: {
sans: 'var(--font-sans)',
mono: 'var(--font-mono)',
},
borderRadius: {
sm: 'var(--radius-sm)',
md: 'var(--radius-md)',
lg: 'var(--radius-lg)',
xl: 'var(--radius-xl)',
},
boxShadow: {
sm: 'var(--shadow-sm)',
md: 'var(--shadow-md)',
lg: 'var(--shadow-lg)',
},
},
},
} satisfies Config;
```
---
## Primitive Components
Primitives are headless (no visual opinions) or minimally styled. They handle accessibility and behavior; Composites handle visual design.
```tsx
// components/primitives/Button.tsx
import { forwardRef, ButtonHTMLAttributes } from 'react';
import { cva, type VariantProps } from 'class-variance-authority';
const button = cva(
// Base — always applied
[
'inline-flex items-center justify-center gap-2',
'font-medium rounded-md',
'transition-colors duration-150',
'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-brand focus-visible:ring-offset-2',
'disabled:pointer-events-none disabled:opacity-50',
],
{
variants: {
variant: {
primary: 'bg-brand text-text-inverse hover:bg-brand-hover',
secondary: 'bg-surface-overlay text-text-primary hover:bg-border',
ghost: 'text-text-primary hover:bg-surface-overlay',
danger: 'bg-error text-white hover:bg-red-600',
outline: 'border border-border text-text-primary hover:bg-surface-raised',
},
size: {
sm: 'h-8 px-3 text-sm',
md: 'h-10 px-4 text-sm',
lg: 'h-12 px-6 text-base',
},
},
defaultVariants: { variant: 'primary', size: 'md' },
}
);
interface ButtonProps
extends ButtonHTMLAttributes<HTMLButtonElement>,
VariantProps<typeof button> {
loading?: boolean;
}
export const Button = forwardRef<HTMLButtonElement, ButtonProps>(
({ className, variant, size, loading, children, disabled, ...props }, ref) => (
<button
ref={ref}
disabled={disabled || loading}
aria-busy={loading}
className={button({ variant, size, className })}
{...props}
>
{loading && <Spinner size="sm" aria-hidden="true" />}
{children}
</button>
)
);
Button.displayName = 'Button';
```
---
## Dark Mode Toggle
```tsx
// providers/ThemeProvider.tsx
'use client';
import { createContext, useContext, useEffect, useState } from 'react';
type Theme = 'light' | 'dark' | 'system';
const ThemeContext = createContext<{
theme: Theme;
setTheme: (t: Theme) => void;
}>({ theme: 'system', setTheme: () => {} });
export function ThemeProvider({ children }: { children: React.ReactNode }) {
const [theme, setThemeState] = useState<Theme>('system');
useEffect(() => {
const stored = localStorage.getItem('theme') as Theme | null;
if (stored) setThemeState(stored);
}, []);
useEffect(() => {
const root = document.documentElement;
const isDark =
theme === 'dark' ||
(theme === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches);
root.setAttribute('data-theme', isDark ? 'dark' : 'light');
localStorage.setItem('theme', theme);
}, [theme]);
return (
<ThemeContext.Provider value={{ theme, setTheme: setThemeState }}>
{children}
</ThemeContext.Provider>
);
}
export const useTheme = () => useContext(ThemeContext);
```
---
## Storybook Documentation
```tsx
// components/primitives/Button.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import { Button } from './Button';
const meta: Meta<typeof Button> = {
component: Button,
tags: ['autodocs'], // Auto-generate docs from JSDoc + props
argTypes: {
variant: { control: 'select' },
size: { control: 'select' },
loading: { control: 'boolean' },
disabled: { control: 'boolean' },
},
};
export default meta;
type Story = StoryObj<typeof Button>;
export const Primary: Story = { args: { children: 'Button', variant: 'primary' } };
export const Secondary: Story = { args: { children: 'Button', variant: 'secondary' } };
export const Loading: Story = { args: { children: 'Saving', loading: true } };
export const Disabled: Story = { args: { children: 'Disabled', disabled: true } };
// Comprehensive variant matrix
export const AllVariants: Story = {
render: () => (
<div className="flex flex-wrap gap-3">
{(['primary', 'secondary', 'ghost', 'danger', 'outline'] as const).map(v => (
<Button key={v} variant={v}>{v}</Button>
))}
</div>
),
};
```
---
## Checklist
- [ ] Design tokens defined as CSS Custom Properties (not hardcoded values in components)
- [ ] Semantic tokens used in components (not palette tokens directly)
- [ ] Dark mode swaps semantic tokens only (palette tokens unchanged)
- [ ] Component variants use `cva` (class-variance-authority) — not inline ternaries
- [ ] All interactive components have `focus-visible` ring
- [ ] Storybook story per component with all variant/state combinations
- [ ] No magic numbers in components — always a token reference
- [ ] Typography scale uses `--text-*` tokens, not arbitrary `text-[17px]`
- [ ] Spacing uses scale (`p-4`, `gap-6`) — never arbitrary spacing
- [ ] `forwardRef` on all primitive components (allows composition)Related Skills
typography-design
Typography as a creative discipline: typeface selection criteria, type pairing (serif + sans, display + body), modular scale systems, line-height and tracking ratios, hierarchy construction, and web/mobile rendering considerations. The decisions behind design tokens, not the tokens themselves.
sdk-design-patterns
SDK design patterns — API ergonomics, backward compatibility (semantic versioning, deprecation), multi-language SDK generation (openapi-generator vs Speakeasy), error hierarchy design, SDK testing strategies, and documentation as first-class SDK artifact.
presentation-design
Presentation structure, narrative design, and slide layout principles. Covers the problem-solution-evidence arc, slide density rules (one idea per slide), slide type catalogue, opening hooks, and closing patterns. Use when structuring any slide deck — conference talk, demo, investor pitch, or team update.
marketing-design
Marketing asset design for developers: Open Graph / social media card specs and HTML generation, email template HTML/CSS patterns (table-based layout, Outlook compatibility, dark mode), banner and ad creative dimensions, print-safe PDF generation, and brand consistency across marketing touchpoints. From OG image code to email that renders in Outlook.
liquid-glass-design
iOS 26 Liquid Glass design system — dynamic glass material with blur, reflection, and interactive morphing for SwiftUI, UIKit, and WidgetKit.
icon-system
SVG icon system design: icon library selection (Lucide, Phosphor, Heroicons), custom icon brief writing, SVG optimization with SVGO, icon tokens (size, color, stroke), accessibility (aria-label, title, role), sprite sheet generation, icon naming conventions, and icon-to-code workflow. From picking an icon set to shipping accessible, performant icons.
generative-ai-design
AI-assisted design workflows: prompt engineering for image generation (Midjourney, DALL-E 3, Stable Diffusion, Flux), achieving style consistency across a generated asset set, post-processing AI outputs for production use, legal and licensing considerations, and when AI generation is and isn't appropriate. For teams integrating generative AI into their design workflow.
experiment-design
A/B testing and experimentation workflow: hypothesis design, metric selection, sample size calculation, statistical significance, common pitfalls (peeking, SRM, novelty effect), and experiment lifecycle. Complements feature-flags (implementation) with statistical rigor.
design-ops
Design Operations: Figma file organization standards, design-to-dev handoff workflow, design QA checklist, design token sync pipeline (Figma Variables → Style Dictionary → CSS/Tailwind), design system versioning and governance, component audit methodology, and design-dev collaboration patterns. Bridges the gap between design tools and production code.
dashboard-design
Dashboard architecture and UX: KPI hierarchy, information density decisions, filter patterns, drill-down navigation, real-time update strategies (polling vs. WebSocket vs. SSE), empty and loading states for charts, and responsive dashboard layouts. Use when designing or building any analytics dashboard.
api-design-advanced
Advanced API design — per-language implementation patterns (TypeScript/Next.js, Go/net-http), anti-patterns (200 for everything, 500 for validation, contract breaking), and full pre-ship checklist.
api-design
REST API design patterns including resource naming, status codes, pagination, filtering, error responses, versioning, and rate limiting for production APIs.