Design systems are the bridge between design and engineering: a shared language of components, tokens, and processes that lets teams build consistently, faster, and with fewer surprises. This guide explains three practical pillars โ building reusable components, implementing design tokens, and integrating Figma into the workflow โ with concrete examples and actionable recommendations.
Core terms & abbreviations
- Design System: A collection of reusable components, design tokens, documentation, and processes that help teams design and build consistent products.
- Design Token: A named value (color, spacing, type size, etc.) that represents a design decision in a platform-agnostic format (JSON/YAML) and can be transformed for each target platform.
- Figma: A cloud-based design tool used for UI design and collaboration. (Figma docs: https://www.figma.com/)
- Storybook: A UI component explorer used to document and manually test components in isolation. (https://storybook.js.org)
- CI / CD: Continuous Integration / Continuous Delivery โ automated pipelines that run builds, tests, and publish artifacts.
- CSS variable: Runtime variables exposed to the browser (e.g., –color-primary) used to apply tokens in CSS.
- ARIA: Accessible Rich Internet Applications โ attributes and practices that improve accessibility for assistive tech.
- SSR / SSG / CSR: Server-side rendering, Static-site generation, Client-side rendering โ common rendering strategies for web apps.
Abbreviations quick reference: Figma (Figma), CI (Continuous Integration), CD (Continuous Delivery), ARIA (Accessible Rich Internet Applications), JSON (JavaScript Object Notation), YAML (YAML Ain’t Markup Language).
Building reusable components
A reusable component is more than a visual snippet โ it’s a small, predictable system piece that can be composed to build larger UIs. A truly reusable component is:
- Composable: works well inside other components; exposes clear slots/props.
- Configurable: supports variants and theming without breaking internals.
- Accessible: includes ARIA, keyboard behavior, and semantic markup.
- Documented: has usage examples, props, and visual states in a living style guide (e.g., Storybook).
Component anatomy
A solid component typically includes:
- Props: explicit inputs (e.g.,
size,variant,disabled). - Variants: predefined visual styles (
primary,secondary). - States: visual/behavioral states (
hover,focus,loading). - Slots/Composition points: places for children, icons, or headers.
Example (React + TypeScript):
type ButtonProps = {
children: React.ReactNode;
variant?: 'primary' | 'outline';
size?: 'sm' | 'md' | 'lg';
onClick?: () => void;
};
export function Button({ children, variant='primary', size='md', onClick }: ButtonProps) {
const className = `btn ${variant} ${size}`;
return (
<button className={className} onClick={onClick} aria-pressed={variant==='primary'}>
{children}
</button>
);
}
#### Storybook example (Component story)
```tsx
import React from 'react';
import { Button } from './Button';
export default { title: 'Components/Button', component: Button };
export const Primary = () => <Button variant="primary">Primary</Button>;
export const Outline = () => <Button variant="outline">Outline</Button>;
This Storybook story documents the Button visual states and lets designers and engineers validate sizes, variants, and accessibility notes in isolation.
This simple pattern separates API (props) from implementation (class names or styles), which helps keep components stable while internals evolve.
Composition patterns
- Compound components (e.g.,
<Form><Form.Label/><Form.Input/></Form>) provide a flexible API for complex UIs. - Slot-based composition (passing elements as props like
icon={<Icon/>}) keeps markup explicit. - Higher-order patterns like decorators or layout components centralize cross-cutting concerns (spacing, grid placement).
Naming & documentation
- Use clear, consistent naming:
Button, notButton2orPrimaryBtn. - Document prop types, accessibility notes, visual examples, and common usage patterns in Storybook or a component library portal.
Design tokens โ the system’s single source of truth
Design tokens are small, platform-agnostic values (colors, spacing, type sizes) that encode the visual system. Tokens solve drift by centralizing decisions.
Token categories
- Color:
color.brand.primary,color.text.muted. - Spacing:
spacing.4 = 8px. - Typography:
font.size.md,lineHeight.tight. - Elevation:
shadow.xs,shadow.md.
Tokens are usually stored as JSON or YAML and transformed for each platform (CSS variables, iOS plist, Android resources, or JS objects).
Example token JSON:
{
"color": { "brand": { "500": "#2563EB" }, "text": { "default": "#111827" } },
"spacing": { "1": "4px", "2": "8px", "4": "16px" }
}
Naming & organization
- Use hierarchical, semantic names that separate intent from implementation (
color.bg.surfacevscolor.hex_#fff). - Favor tokens by role (e.g.,
bg.surface) rather than raw values to preserve flexibility.
Propagation & toolchain
- Use a token transformer like Style Dictionary to generate platform artifacts.
- Expose tokens as CSS variables for runtime theming:
:root { --color-brand-500: #2563EB; --spacing-2: 8px; }
.btn { padding: var(--spacing-2); background: var(--color-brand-500); }
Token pipeline example
Typical token pipeline (simple):
figma -> tokens repo (tokens.json) -> CI (style-dictionary build) -> npm package / CDN -> apps
Minimal style-dictionary config (example config.json):
{
"source": ["tokens/**/*.json"],
"platforms": {
"css": {
"transformer": "css",
"buildPath": "build/css/",
"files": [{ "destination": "variables.css", "format": "css/variables" }]
},
"js": {
"buildPath": "build/js/",
"files": [{ "destination": "tokens.js", "format": "javascript/es6" }]
}
}
}
Example package.json script to run the transform:
{
"scripts": {
"build:tokens": "style-dictionary build --config config.json"
}
}
CI snippet (GitHub Actions) that builds and publishes tokens on changes to the tokens folder:
name: Token Sync
on:
push:
paths:
- 'tokens/**'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Install
run: npm ci
- name: Build tokens
run: npm run build:tokens
- name: Publish
run: npm publish ./build
Integrating with Figma
Figma is not just a design canvas โ it’s the canonical place designers collaborate and build component libraries. Tight Figma integration reduces friction in the design-to-dev handoff.
Component libraries in Figma
- Use Figma components and variants to mirror your code components: a
Buttoncomponent withprimary/secondaryvariants maps directly to your component API. - Organize components into a shared library and publish updates so designers can adopt new tokens and components consistently.
Tokens from Figma to code
- Extract tokens with tools like Tokens Studio for Figma or export via the Figma Tokens plugin and commit the JSON to a tokens repository.
- Automate token sync with a CI job: on token change, transform tokens into CSS variables and platform artifacts using a tool like Style Dictionary.
Example token sync flow (text graph):
designer -> figma (tokens + components) -> tokens repo -> CI (transform via Style Dictionary) -> npm package or CDN -> apps
Handoff & developer workflow
- Keep a documented mapping of Figma tokens -> code tokens -> CSS variables.
- Use Storybook and Chromatic to align design snapshots with live components; include Figma links in Storybook stories for quick reference.
Common pitfalls & best practices
- Pitfall: copying patterns instead of components โ prefer composition and single source of truth. โ
- Pitfall: token sprawl โ keep tokens limited and role-based (brand vs neutral roles). โ
- Best practice: version tokens and components semantically (MAJOR breaking changes, MINOR additions, PATCH fixes). โ
- Best practice: include accessibility criteria in component docs and run automated accessibility checks (axe) in CI. โ
Practical tip: maintain a lightweight CONTRIBUTING.md for your design system so contributors know how to propose a new token or component.
Additional best practices and checks
- Visual regression testing: integrate tools like Chromatic or Percy to catch visual regressions when components change.
- Automated accessibility checks: run axe-core or pa11y in CI and gate PRs based on accessibility metrics.
- Design-review links: include Figma links inside Storybook stories so reviewers can quickly compare designed vs rendered UI.
- Semantic versioning & changelog: publish components and tokens with clear changelogs so downstream apps can decide when to adopt changes.
Deployment & runtime architecture (text graphs)
Simple token delivery model:
designer -> figma -> tokens repo -> CI (style-dict build) -> npm package -> app build -> CDN -> client
Full runtime architecture for apps consuming the design system (example):
client(browser) -> CDN (static assets) -> web server (SSG/SSR) -> backend API -> database
If you serve tokens at runtime (CSS vars), you can do:
tokens CDN -> client -> apply CSS vars
Pros & cons (when to use a design system)
-
Pros:
- Consistency across products: components and tokens reduce design drift.
- Faster product delivery: engineers reuse components instead of rebuilding patterns.
- Better accessibility & UX quality through centralized checks and standards.
-
Cons:
- Up-front cost: building and maintaining a design system requires effort and governance.
- Can become rigid: overly prescriptive systems slow experimentation if not well-versioned.
- Maintenance burden: tokens and components must be kept in sync with design changes.
Comparison with alternatives:
-
Design System vs Utility-first frameworks (Tailwind):
- Tailwind gives flexibility and speed for building UIs quickly, but it doesn’t provide a centralized token and component governance model. Use Tailwind for rapid composition; add a design system when you need consistency and cross-team alignment.
-
Design System vs Large Component Libraries (MUI, Ant Design, Bootstrap):
- Off-the-shelf libraries accelerate development but sometimes force design compromises. A design system provides more control and brand alignment but takes more effort to build.
If you’d like, I can add short, copyable examples (small repo) demonstrating a Storybook + Style Dictionary setup with GitHub Actions and Chromatic for visual tests.
Using tokens in CSS and JavaScript (practical examples)
After building tokens with Style Dictionary you will often have platform artifacts such as variables.css and tokens.js:
variables.css (generated)
:root {
--color-brand-500: #2563EB;
--spacing-2: 8px;
}
Use in CSS:
.btn { padding: var(--spacing-2); background: var(--color-brand-500); }
tokens.js (generated)
export const color = { brand: { '500': '#2563EB' } };
export const spacing = { '2': '8px' };
Use in JS/React for inline styles or CSS-in-JS:
import { color, spacing } from './build/js/tokens.js';
function InlineButton() {
return <button style={{ padding: spacing['2'], background: color.brand['500'] }}>Inline</button>;
}
Glossary (core abbreviations)
- ARIA โ Accessible Rich Internet Applications. A set of attributes for improving accessibility for assistive technologies (e.g., screen readers). See: https://www.w3.org/WAI/standards-guidelines/aria/
- CI โ Continuous Integration: automated build & test pipelines that run on code changes.
- CD โ Continuous Delivery / Deployment: pipeline steps to publish artifacts (packages, CDN assets) and optionally deploy to production.
- SSG โ Static-site generation: pre-render pages at build time (e.g., Hugo, Next.js static export).
- SSR โ Server-side rendering: rendering HTML on the server on each request.
- CSR โ Client-side rendering: rendering in the browser using JS frameworks.
- Token โ see above; a platform-agnostic value used to generate platform artifacts (CSS vars, platform code, native assets).
- Variant โ A named visual/style variation for a component (e.g.,
primary,secondary,danger). - Component โ An encapsulated UI building block with a defined API (props/inputs), visual representation, and behaviors.
Conclusion โ starting small, scaling safely
Start with a minimal set of tokens (colors, spacing, typography) and a few high-impact components (Button, Input, Card). Publish them in a component library with Storybook and automate token distribution from Figma to code. Over time expand tokens and components, enforce accessibility, and keep documentation current: small, consistent steps win.
Further resources
-
Style Dictionary โ https://amzn.github.io/style-dictionary/
-
Figma docs โ https://www.figma.com/
-
Tokens Studio for Figma โ https://www.tokens-studio.com/
-
Storybook โ https://storybook.js.org/
-
Chromatic (visual testing for Storybook) โ https://www.chromatic.com/
-
Brad Frost โ Atomic Design โ http://bradfrost.com/blog/post/atomic-web-design/
-
Building Design Systems (book) โ https://www.oreilly.com/library/view/building-design-systems/9781492058822/
-
Smashing Magazine โ design systems tag โ https://www.smashingmagazine.com/tag/design-systems/
-
CSS-Tricks โ design token articles โ https://css-tricks.com/tag/design-tokens/
Comments