apps/docs/content/blog/en/what-is-a-design-system.mdx
A design system is a collection of reusable components, design tokens, patterns, and guidelines that help teams build consistent user interfaces at scale. It's both a product and a process — the components your engineers use to build features, the tokens your designers reference in Figma, and the documentation that keeps everyone aligned.
If you've ever shipped a feature where the button padding didn't match the rest of the app, or where one modal used a 16px border radius and another used 12px, you've felt the absence of a design system. This guide explains what a design system actually is, why your team probably needs one, and how modern React component libraries make building them far more practical than it was five years ago.
These three terms get used interchangeably, but they're different things at different levels of abstraction.
A style guide documents visual standards: colors, typography, spacing, iconography, and logo usage. It tells you what things should look like but doesn't give you tools to build them.
Example: "Primary buttons use the accent token, 14px semibold text, 8px vertical padding, 16px horizontal padding, and a 12px radius."
A component library is a collection of reusable UI components. It tells you how to build things but doesn't necessarily explain when to use them or why they look that way.
Example: A Button component in a package like @heroui/react that accepts size and semantic variant props.
A design system combines both and adds process, documentation, and governance. It tells you what things should look like, how to build them, when to use which pattern, and how to contribute changes.
Components of a design system:
| Layer | Purpose | Example |
|---|---|---|
| Design tokens | Shared values for color, spacing, typography, shadows | --accent: oklch(0.65 0.24 260) |
| Component library | Reusable UI building blocks | <Button>, <Card>, <Table> |
| Patterns | Repeatable solutions to common design problems | Form validation pattern, empty state pattern |
| Documentation | Usage guidelines, do's and don'ts, accessibility notes | "Use destructive buttons only for irreversible actions" |
| Contribution model | Process for proposing, reviewing, and shipping changes | RFC process, design review, release cycle |
Without a design system, every developer makes independent decisions about spacing, colors, and interaction patterns. With five developers, you might get five different approaches. With fifty, you get chaos.
A design system centralizes these decisions. When the primary color changes, you update one token and it propagates everywhere. When the team agrees on a new modal pattern, it's documented and available for everyone.
Design systems save time by eliminating redundant work. Instead of designing and building a data table from scratch for every feature, teams use the existing Table component and focus on the data model and business logic that's unique to their feature.
The speed gains compound over time. The first team to use the design system saves a little. The twentieth team saves a lot.
Components in a design system are built once and improved continuously. Accessibility, keyboard navigation, screen reader support, responsive behavior, and edge cases are handled in the component library rather than reimplemented (with varying quality) across features.
Design systems give teams a common language. When a designer says "use a Card with a flat variant," the developer knows exactly what component and props to use. This reduces back-and-forth between design and engineering.
Design tokens are the atomic values that define your visual language. They're the single source of truth for colors, spacing, typography, shadows, borders, and motion.
In modern systems, tokens are typically expressed as CSS custom properties:
@theme {
--color-accent: var(--accent);
--color-background: var(--background);
--color-foreground: var(--foreground);
--radius-md: calc(var(--radius) * 0.75);
--shadow-surface: var(--surface-shadow);
}
Tailwind CSS v4 uses a CSS-first token system with @theme, which HeroUI builds on. HeroUI's shipped theme maps real CSS variables such as --accent, --background, --foreground, --radius, and --surface-shadow into Tailwind utilities.
Why tokens matter:
#f3f4f6 or #f4f5f7.Modern component libraries use two main patterns:
Compound components expose sub-components that compose together:
<Card>
<Card.Header>
<h3>Title</h3>
</Card.Header>
<Card.Content>
<p>Content goes here</p>
</Card.Content>
<Card.Footer>
<Button>Action</Button>
</Card.Footer>
</Card>
HeroUI uses this pattern. Each sub-component is independently styleable, and you can omit parts you don't need. The parent component manages shared state (like selection in a RadioGroup) while children control their own rendering.
Monolithic components accept all configuration through props:
<Card
title="Title"
description="Content goes here"
footer={<Button>Action</Button>}
/>
This is simpler for basic use cases but becomes rigid when you need custom layouts, conditional rendering, or non-standard markup.
Which is better? Compound components scale better for design systems because they give consuming teams more control without requiring library changes. When a team needs to add an icon between the title and description, they just add it — no new prop needed.
The best design systems build accessibility into the foundation layer, not the component layer. This means using a primitive library like React Aria or Radix UI that handles:
HeroUI builds on React Aria, one of the most comprehensive accessibility primitive libraries available for React. This means HeroUI components — from Button to Calendar to ComboBox — inherit battle-tested accessibility behavior.
The fastest path to a design system is adopting an existing component library and extending it. This gives you:
Best for: Teams that want to move fast and don't have unique design requirements that existing libraries can't accommodate.
Recommended libraries:
| Library | Styling | Best For |
|---|---|---|
| HeroUI | Tailwind CSS v4 | Modern stack, accessibility, AI tooling |
| shadcn/ui | Tailwind CSS | Maximum code ownership |
| MUI | Emotion / sx prop, with Pigment CSS experimental | Material Design, enterprise |
| Mantine | CSS Modules | Maximum component breadth |
If you need a fully custom design language, build your components on top of accessibility primitives:
Best for: Teams with dedicated design system engineers and unique design requirements.
Many teams start by adopting a library (option 1) and gradually extend it. HeroUI supports this through:
This hybrid approach gives you the speed of a pre-built library with the flexibility to diverge where your product needs it.
Tailwind v4 lets you define design tokens directly in CSS:
@import "tailwindcss";
@import "@heroui/styles";
:root {
--accent: oklch(0.6204 0.195 253.83);
--accent-foreground: var(--snow);
--radius: 0.5rem;
--surface-shadow:
0 2px 4px 0 rgba(0, 0, 0, 0.04), 0 1px 2px 0 rgba(0, 0, 0, 0.06),
0 0 1px 0 rgba(0, 0, 0, 0.06);
}
These tokens become Tailwind utilities automatically:
<div className="rounded-md bg-accent shadow-surface">
<p className="text-accent-foreground">Styled with HeroUI tokens</p>
</div>
Organize tokens in layers:
--snow, --eclipse)--background, --foreground, --accent, --surface)@theme (--color-accent, --color-background, --radius-md)HeroUI uses this layered approach. You can override at any level — change the primary color globally, adjust the card radius specifically, or create an entirely new theme.
Don't build a design system before you need one. If you're a team of three building an MVP, adopting a component library is enough. The system should emerge from patterns you discover, not be designed upfront.
A design system is a product, not a project. It needs ongoing investment — new components, bug fixes, documentation updates, and user support. If you build it and walk away, it'll be outdated within months.
If your design system is hard to use, developers will work around it. Prioritize:
Bolting accessibility onto an existing component library is painful and often incomplete. Choose a foundation (React Aria, Radix UI) that handles accessibility from the start.
HeroUI provides the component library and token system layers of a design system:
You still need to add your own patterns, documentation, and governance on top — but the engineering-heavy parts (accessible components, a token system, theme support) are handled.