Appearance
Design System Basics β
A design system is not a UI kit --- it is the single source of truth that keeps your SaaS product consistent as your team and codebase scale.
Why This Matters β
Without a design system, every developer and designer reinvents the wheel. Buttons look different on every page. Spacing is inconsistent. Colors drift. The product feels stitched together rather than unified.
| Role | Why You Should Care |
|---|---|
| π’ Owner | Inconsistent UI erodes trust. A design system reduces design/dev time by 30-50% once established. |
| π» Dev | A component library means building features, not rebuilding buttons. Fewer bugs, faster shipping. |
| π PM | Consistent patterns let you spec features faster. "Use the standard data table" vs. describing every detail. |
| π¨ Designer | Frees you from pixel-pushing to focus on solving actual user problems. |
The Concept (Simple) β
Think of a design system like LEGO bricks. Each brick (component) is well-defined, consistent, and connects to other bricks in predictable ways. You don't redesign the brick every time --- you combine existing bricks to build new things.
A design system has three layers:
βββββββββββββββββββββββββββββββββββββββ
β PATTERNS β β How components combine
β (forms, data tables, navigation) β into common layouts
βββββββββββββββββββββββββββββββββββββββ€
β COMPONENTS β β Reusable UI elements
β (buttons, inputs, cards, modals) β built from tokens
βββββββββββββββββββββββββββββββββββββββ€
β TOKENS β β Foundational values
β (colors, spacing, typography) β everything inherits from
βββββββββββββββββββββββββββββββββββββββChange a token, and everything built on it updates. Change a component, and every pattern using it updates. That is the power.
How It Works (Detailed) β
Design Tokens β
Tokens are the atomic values your entire UI inherits from. They are named, not hard-coded.
Color Tokens:
| Token Name | Value | Usage |
|---|---|---|
--color-primary | #2563EB | Primary buttons, links, active states |
--color-primary-hover | #1D4ED8 | Hover state for primary elements |
--color-secondary | #64748B | Secondary buttons, muted text |
--color-success | #16A34A | Success messages, positive indicators |
--color-warning | #D97706 | Warnings, caution states |
--color-danger | #DC2626 | Errors, destructive actions |
--color-bg-primary | #FFFFFF | Main background |
--color-bg-secondary | #F8FAFC | Card backgrounds, sidebar |
--color-bg-tertiary | #F1F5F9 | Table row hover, input backgrounds |
--color-border | #E2E8F0 | Borders, dividers |
--color-text-primary | #0F172A | Headings, body text |
--color-text-secondary | #64748B | Captions, labels, hints |
Spacing Scale:
Token Value Usage
ββββββββββββββββββββββββββββββββββββββββββββββ
--space-1 4px Tight internal padding
--space-2 8px Icon-to-label gap
--space-3 12px Small component padding
--space-4 16px Standard component padding
--space-5 20px Card internal padding
--space-6 24px Section spacing
--space-8 32px Major section breaks
--space-10 40px Page-level padding
--space-12 48px Large section separators
--space-16 64px Hero/banner spacingTypography Scale:
| Token | Size | Weight | Line Height | Usage |
|---|---|---|---|---|
--text-xs | 12px | 400 | 16px | Labels, captions, badges |
--text-sm | 14px | 400 | 20px | Secondary text, table cells |
--text-base | 16px | 400 | 24px | Body text, inputs |
--text-lg | 18px | 500 | 28px | Card titles, sub-headings |
--text-xl | 20px | 600 | 28px | Section headings |
--text-2xl | 24px | 600 | 32px | Page titles |
--text-3xl | 30px | 700 | 36px | Dashboard KPIs |
Why tokens, not raw values?
BAD: .button { background: #2563EB; } β Magic number. What is this?
BAD: .card { background: #2563EB; } β Same color, but is that intentional?
GOOD: .button { background: var(--color-primary); } β Clear intent
GOOD: .card { background: var(--color-bg-secondary); } β Different token, clear purposeIf you rebrand and your primary color changes from blue to purple, you update ONE token. Every button, link, and active state updates automatically.
Component Library Structure β
A well-organized component library follows an atomic design hierarchy.
COMPONENT HIERARCHY
===================
PRIMITIVES (atoms)
βββ Button [primary | secondary | ghost | danger]
βββ Input [text | number | email | password]
βββ Checkbox
βββ Radio
βββ Toggle
βββ Badge [info | success | warning | danger]
βββ Avatar [sm | md | lg | xl]
βββ Icon
βββ Tooltip
βββ Spinner
COMPOSITES (molecules)
βββ Form Field = Label + Input + Help Text + Error
βββ Search Bar = Icon + Input + Clear Button
βββ Dropdown = Button + Menu + Menu Items
βββ Breadcrumb = Links + Separators
βββ Pagination = Buttons + Page Numbers
βββ Tab Group = Tab Items + Active Indicator
βββ Alert = Icon + Text + Dismiss Button
βββ Tag Input = Input + Badge list
PATTERNS (organisms)
βββ Data Table = Table + Pagination + Sort + Filter
βββ Form = Form Fields + Buttons + Validation
βββ Modal = Overlay + Card + Header + Footer
βββ Sidebar Nav = Nav Groups + Nav Items + Collapse
βββ Command Palette = Search + Results + Keyboard Nav
βββ Card Grid = Cards + Responsive Layout
βββ Settings Panel = Sections + Form Fields + Save
βββ Empty State = Illustration + Text + CTAEach component should define:
- [ ] Props/variants --- what configurations are available
- [ ] States --- default, hover, focus, active, disabled, loading, error
- [ ] Accessibility --- ARIA labels, keyboard navigation, focus management
- [ ] Responsive behavior --- how it adapts at breakpoints
- [ ] Usage guidelines --- when to use (and when not to)
Build vs Buy Comparison β
| Factor | Build Your Own | Use Existing (Radix, Headless UI, shadcn) |
|---|---|---|
| Time to start | 3-6 months | 1-2 weeks |
| Customization | Total control | Moderate to high (depends on library) |
| Maintenance | Your team owns it all | Community + your customization layer |
| Consistency | As good as your discipline | Strong baseline, you extend |
| Accessibility | Must build from scratch | Often built-in |
| Cost | High dev hours upfront | Low upfront, possible constraints later |
| Best for | Large teams (10+ devs), unique needs | Small-to-mid teams, standard SaaS patterns |
Recommendation for most SaaS startups:
START HERE ββ> Use headless component library (Radix, Headless UI)
β
βΌ
Add your design tokens (colors, spacing, fonts)
β
βΌ
Build a thin wrapper layer (your <Button>, your <Input>)
β
βΌ
Compose into patterns (your <DataTable>, your <FormLayout>)
β
βΌ
Document in Storybook or similar
β
βΌ
ONLY build custom primitives when existing ones
genuinely cannot meet your needsDocumentation and Adoption β
A design system nobody uses is just a side project. Adoption requires:
Documentation structure:
docs/design-system/
βββ getting-started.md β Installation, setup
βββ principles.md β Design philosophy
βββ tokens/
β βββ colors.md
β βββ spacing.md
β βββ typography.md
βββ components/
β βββ button.md β Props, variants, examples
β βββ input.md
β βββ data-table.md
β βββ ...
βββ patterns/
β βββ forms.md β How to compose form layouts
β βββ navigation.md
β βββ empty-states.md
βββ changelog.md β What changed, migration guidesAdoption checklist:
- [ ] Components are installable via package manager (npm, internal registry)
- [ ] Storybook (or equivalent) is deployed and accessible to the whole team
- [ ] Each component has at least one copy-pasteable usage example
- [ ] Designers use the same token names in Figma as devs use in code
- [ ] New hires get a design system walkthrough in their first week
- [ ] There is a Slack channel or forum for questions and proposals
- [ ] Breaking changes follow semver and include migration guides
Design System Maturity Model β
Not every team needs a full design system on day one. Grow it as your product grows.
MATURITY LEVELS
===============
Level 0: AD HOC
βββ No shared components
βββ Each page styled independently
βββ Inconsistency is the norm
βββ Every feature takes maximum effort
β
βΌ
Level 1: SHARED STYLES
βββ Common CSS/token file
βββ Basic color and font consistency
βββ Components duplicated (not shared)
βββ "It looks roughly the same"
β
βΌ
Level 2: COMPONENT LIBRARY
βββ Shared, importable components
βββ Documented props and variants
βββ Storybook or equivalent
βββ Devs use components instead of raw HTML
β
βΌ
Level 3: DESIGN SYSTEM
βββ Tokens + Components + Patterns + Docs
βββ Figma library mirrors code library
βββ Governance: proposal process for changes
βββ Used across multiple products or surfaces
βββ Dedicated owner (person or team)
β
βΌ
Level 4: PLATFORM
βββ Design system as internal product
βββ Versioned, published, consumed by teams
βββ Contribution model (teams submit components)
βββ Analytics: usage tracking, adoption metrics
βββ Only needed for large orgs (50+ devs)Where you should be based on team size:
| Team Size | Target Maturity | Timeline |
|---|---|---|
| 1-3 devs | Level 1 (Shared Styles) | Immediately |
| 4-8 devs | Level 2 (Component Library) | Within first quarter |
| 9-20 devs | Level 3 (Design System) | Within 6 months |
| 20+ devs | Level 3-4 | Ongoing investment |
In Practice β
Example: Defining a Button Component β
Here is what a well-documented button component looks like.
BUTTON COMPONENT
================
Variants: [primary] [secondary] [ghost] [danger]
Sizes: [sm] [md] [lg]
States: default | hover | focus | active | disabled | loading
Props:
ββββββββββββββββ¬βββββββββββ¬ββββββββββββ¬βββββββββββββββββββββββββββ
β Prop β Type β Default β Description β
ββββββββββββββββΌβββββββββββΌββββββββββββΌβββββββββββββββββββββββββββ€
β variant β string β "primary" β Visual style β
β size β string β "md" β Button size β
β disabled β boolean β false β Prevents interaction β
β loading β boolean β false β Shows spinner, disables β
β leftIcon β ReactNodeβ null β Icon before label β
β rightIcon β ReactNodeβ null β Icon after label β
β fullWidth β boolean β false β Stretches to container β
β onClick β function β - β Click handler β
ββββββββββββββββ΄βββββββββββ΄ββββββββββββ΄βββββββββββββββββββββββββββ
Usage Guidelines:
- Use PRIMARY for the single most important action on the page
- Use SECONDARY for alternative actions alongside a primary
- Use GHOST for low-emphasis actions (cancel, dismiss)
- Use DANGER only for destructive/irreversible actions
- Never place two PRIMARY buttons side by side
- Always include a text label (icon-only buttons need aria-label)Common Mistakes β
| Mistake | Why It Happens | Fix |
|---|---|---|
| Building too much too soon | Designing for hypothetical future needs | Build components as features need them |
| No single owner | "Everyone owns it" means nobody does | Assign a maintainer, even part-time |
| Design-code drift | Figma and code diverge over months | Sync reviews quarterly, automate where possible |
| Over-engineering tokens | Tokens for every conceivable value | Start with 80/20: the 20 tokens that cover 80% of cases |
| No versioning | Breaking changes surprise consumers | Use semver from day one |
| Ignoring accessibility | "We'll add it later" | Bake it into components from the start --- retrofitting is 10x harder |
Key Takeaways β
- A design system has three layers: tokens (values), components (elements), and patterns (compositions)
- Design tokens replace magic numbers with named, meaningful values that propagate changes automatically
- Start with a headless component library and add your token layer on top --- do not build from scratch unless you must
- Documentation and adoption strategy matter as much as the components themselves
- Grow your system's maturity alongside your team size --- Level 2 is the sweet spot for most early SaaS teams
- Accessibility is not optional and is dramatically cheaper to include from the start
Action Items β
| Role | Next Step |
|---|---|
| π’ Owner | Assess your current maturity level using the model above. Budget time to reach the next level. |
| π» Dev | Set up a shared token file (CSS variables or theme object) and migrate the 5 most common colors and spacing values. |
| π PM | Identify the 10 most-used components in your product. These are your priority for standardization. |
| π¨ Designer | Create a Figma component library that mirrors the token names and component variants your devs use. Align naming conventions. |
Previous: Chapter 16 --- SaaS UX Principles | Next: Chapter 18 --- Designing for Roles