Design Systems
Build scalable, maintainable design systems like Shopify and Atlassian
Design Systems
Design systems are the foundation of consistent, scalable UIs. Companies like Shopify, Atlassian, and GitHub use sophisticated design systems to maintain quality across hundreds of products and thousands of components.
What is a Design System?
A design system is more than a component library—it's a complete set of standards, documentation, and principles that guide product design and development.
Components of a Design System:
- Design Tokens: Colors, spacing, typography values
- Component Library: Reusable UI components
- Documentation: Usage guidelines, do's and don'ts
- Patterns: Common UI patterns and solutions
- Principles: Design philosophy and values
Why Design Systems Matter
Benefits:
- Consistency: Same look and feel everywhere
- Speed: Build faster with reusable components
- Quality: Battle-tested, accessible components
- Scalability: Maintain quality as team grows
- Collaboration: Common language for designers and developers
Problems They Solve:
- Inconsistent UI across products
- Duplicate components with different APIs
- Slow feature development
- Accessibility issues
- Difficult to implement design changes
Anatomy of a Design System
Design System
├── Design Tokens
│ ├── Colors (primitives + semantic)
│ ├── Typography (font families, sizes, weights)
│ ├── Spacing (margins, paddings, gaps)
│ ├── Shadows (elevation system)
│ ├── Borders (radius, widths)
│ └── Breakpoints (responsive system)
│
├── Components
│ ├── Primitives (Button, Input, Text)
│ ├── Layout (Stack, Grid, Flex)
│ ├── Feedback (Alert, Toast, Modal)
│ ├── Navigation (Nav, Tabs, Breadcrumbs)
│ └── Complex (DataTable, Calendar, Editor)
│
├── Patterns
│ ├── Forms (validation, layout)
│ ├── Navigation (menus, sidebars)
│ ├── Data Display (tables, lists, cards)
│ └── Feedback (loading, errors, empty states)
│
└── Documentation
├── Getting Started
├── Design Principles
├── Component Docs (props, examples, accessibility)
└── Contribution GuidelinesDesign Tokens Architecture
Design tokens are the atomic building blocks:
// ❌ BAD: Hardcoded values
<button style={{
color: '#0066CC',
padding: '12px 24px',
borderRadius: '6px',
fontSize: '14px'
}}>
Click me
</button>
// ✅ GOOD: Design tokens
<button style={{
color: tokens.color.primary,
padding: `${tokens.spacing[3]} ${tokens.spacing[6]}`,
borderRadius: tokens.borderRadius.md,
fontSize: tokens.fontSize.sm
}}>
Click me
</button>Token Hierarchy
Primitive Tokens (Raw Values)
// tokens/primitives.ts
export const primitives = {
color: {
blue: {
50: '#EFF6FF',
100: '#DBEAFE',
200: '#BFDBFE',
500: '#3B82F6',
700: '#1D4ED8',
900: '#1E3A8A',
},
gray: {
50: '#F9FAFB',
100: '#F3F4F6',
500: '#6B7280',
900: '#111827',
},
},
spacing: {
0: '0',
1: '0.25rem', // 4px
2: '0.5rem', // 8px
3: '0.75rem', // 12px
4: '1rem', // 16px
6: '1.5rem', // 24px
8: '2rem', // 32px
},
};Semantic Tokens (Meaning)
// tokens/semantic.ts
export const semantic = {
color: {
primary: primitives.color.blue[500],
secondary: primitives.color.gray[500],
background: {
default: '#FFFFFF',
subtle: primitives.color.gray[50],
},
text: {
default: primitives.color.gray[900],
muted: primitives.color.gray[500],
},
border: {
default: primitives.color.gray[200],
hover: primitives.color.gray[300],
},
feedback: {
success: '#10B981',
warning: '#F59E0B',
error: '#EF4444',
info: primitives.color.blue[500],
},
},
spacing: {
xs: primitives.spacing[1],
sm: primitives.spacing[2],
md: primitives.spacing[4],
lg: primitives.spacing[6],
xl: primitives.spacing[8],
},
};Component API Design Principles
1. Consistent Naming
// ✅ GOOD: Consistent prop names
<Button variant="primary" size="md" disabled />
<Input variant="outline" size="md" disabled />
<Select variant="filled" size="md" disabled />
// ❌ BAD: Inconsistent naming
<Button type="primary" btnSize="medium" isDisabled />
<Input style="outline" inputSize="md" readonly />
<Select appearance="filled" selectSize="m" inactive />2. Composition Over Configuration
// ✅ GOOD: Composable
<Card>
<CardHeader>
<CardTitle>Title</CardTitle>
</CardHeader>
<CardContent>
Content here
</CardContent>
<CardFooter>
<Button>Action</Button>
</CardFooter>
</Card>
// ❌ BAD: Props explosion
<Card
title="Title"
content="Content here"
footerActions={[{ label: 'Action', onClick: fn }]}
showHeader
showFooter
/>3. Sensible Defaults
// Button with smart defaults
<Button>Submit</Button>
// Defaults to: variant="primary", size="md", type="button"
<Button variant="ghost">Cancel</Button>
// Only override what's neededDesign System Layers
Layer 1: Tokens
// Immutable values
export const tokens = {
color: { ... },
spacing: { ... },
typography: { ... },
};Layer 2: Primitives
// Basic building blocks
import { Button, Input, Text, Box } from '@/components/primitives';Layer 3: Patterns
// Common compositions
import { Form, FormField, FormError } from '@/components/patterns';Layer 4: Features
// Domain-specific components
import { ProductCard, CheckoutForm } from '@/features';Theming Architecture
// Multi-theme support
const themes = {
light: {
background: '#FFFFFF',
text: '#000000',
primary: '#0066CC',
},
dark: {
background: '#000000',
text: '#FFFFFF',
primary: '#3B82F6',
},
brand: {
background: '#F5F5F5',
text: '#1A1A1A',
primary: '#FF6B00',
},
};
// Theme provider
<ThemeProvider theme={themes.light}>
<App />
</ThemeProvider>Real-World Examples
Shopify Polaris
- 50+ components
- Comprehensive documentation
- Built-in accessibility
- Mobile-first design
Atlassian Design System
- Token-based architecture
- Dark mode support
- Cross-platform (web, mobile, desktop)
- Extensive patterns library
GitHub Primer
- React components
- ViewComponent (Rails)
- Figma library
- Open source
Building Your Design System
1. Start Small
Phase 1: Foundation
- Design tokens
- Basic primitives (Button, Input, Text)
- Typography system
- Color palette
Phase 2: Components
- Common components (10-15)
- Documentation
- Storybook
Phase 3: Patterns
- Form patterns
- Navigation patterns
- Data display
Phase 4: Scale
- Advanced components
- Animation system
- Contribution guidelines2. Token-First Approach
Start with design tokens, then build components using them.
3. Documentation-Driven
Document before building—clarify API design first.
4. Accessibility Built-In
Every component should be accessible by default.
5. Version and Maintain
Treat your design system as a product—version it, maintain it, improve it.
Best Practices
- Token-Based: Everything references tokens
- Type-Safe: TypeScript for all components
- Accessible: WCAG AA minimum
- Documented: Clear examples and guidelines
- Testable: Unit + visual regression tests
- Versioned: Semantic versioning
- Composable: Small, reusable pieces
- Themeable: Support multiple themes
- Responsive: Mobile-first design
- Maintainable: Clear ownership and processes
Common Pitfalls
❌ Too many variants: 20 button variants
✅ 3-5 core variants, compose for variations
❌ Prop overload: 50 props per component
✅ Composition and sensible defaults
❌ Inconsistent naming: Different conventions
✅ Establish naming guidelines
❌ No versioning: Breaking changes everywhere
✅ Semantic versioning with changelogs
❌ Poor documentation: "Just read the code"
✅ Examples, guidelines, accessibility notes
Tools and Libraries
Component Development:
- Storybook: Component explorer
- Chromatic: Visual testing
- Radix UI: Unstyled, accessible primitives
- Headless UI: Tailwind's component library
Token Management:
- Style Dictionary: Token transforms
- Theo: Salesforce's token tool
- Figma Tokens: Design-to-code sync
Documentation:
- Docusaurus: Documentation sites
- Fumadocs: Next.js docs (what you're reading!)
- VuePress: Vue-based docs
Measuring Success
Key Metrics:
- Component reuse rate
- Time to build new features
- Design consistency score
- Developer satisfaction
- Accessibility compliance
Next Steps
Explore specific design system topics:
- Design Tokens: Token architecture
- Component API Design: Good APIs
- Theming Architecture: Multi-theme support
- Responsive Design Tokens: Responsive system
- Dark Mode Implementation: Proper dark mode
- Typography System: Type scale
- Spacing System: Spacing scale
A great design system is the foundation of a great product—invest in it early and maintain it well.