Design Systems That Teams Actually Use
A design system is not a component library. It is a shared vocabulary between design and engineering. If the vocabulary is not obvious, nobody speaks it.
Article focus
80% adoption
When governance is light and obvious
Key takeaways
- A design system fails when it prioritizes completeness over clarity. Start with the 20% of components that cover 80% of the surfaces.
- Naming conventions must match the designer's vocabulary. If the design file calls it "HeroSection," the code component should too.
- Contribution workflows matter more than the component code. If adding a component takes three approvals, developers will build their own.
Why do most design systems fail?
Because they optimize for completeness instead of adoption. A perfect button component means nothing if teams keep building their own.
I have watched teams spend six months building an exhaustive component library, only to find that the product teams still import Material-UI or write custom CSS. The design system was technically excellent - every component had variants, dark mode, accessibility, and a Storybook page. But nobody used it.
The failure is not technical. It is social. A design system is a product whose users are developers. If the API is awkward, the docs are hard to navigate, or the contribution process takes a week, developers will route around it.
The fix is to treat the design system like any other product: ship fast, iterate based on feedback, and measure adoption ruthlessly.
Beginner, Builder, and Expert lens
Click each lens to see how the same section can teach the basics without losing depth.
Click to switch the reading lens
Beginner, builder, and expert views stay in the same section so the article works for multiple skill levels.
Start with vocabulary, the smallest useful component set, and a clear path to copy-paste less.
Start with the 20% that matters
Identify the components that appear on the most surfaces. Button, Card, Input, Select, Modal, Table. Build those well. Skip the rest until someone asks.
The Pareto principle applies brutally to design systems. Twenty percent of the components cover eighty percent of the UI surfaces. If you build Button, Card, Input, Select, Modal, and Table with solid APIs and proper documentation, teams can build almost any page without custom CSS.
Everything else - the fancy hero animation, the custom chart tooltip, the one-off marketing CTA - should be treated as a product component, not a design system primitive. Let the team that needs it build it, and if it gets used three times, promote it to the shared library. This maps directly to the primitive/product/page model from the Component Design deep-dive.
This keeps the design system small, well-maintained, and high-signal. Every component in it has earned its place.
Core surface picker
Click the component you would standardize first to see why it matters in a real team workflow.
Click the core surface you would ship first
This section helps beginners spot the obvious starting points and helps experts judge reuse potential.
Why this matters
Button is the current focus because it is one of the highest-frequency surfaces in the system. The more often a component appears, the more it rewards a simple API and a clear visual state.
Naming matters more than you think
The component name in code must match the name in design files. If designers call it "Primary Action Button," the code component should too.
The biggest adoption barrier I see is vocabulary mismatch. The design file calls it "Page Section." The code calls it "ContainerBlock." The developer spends five minutes mapping the two. Five minutes per component, per developer, per week adds up to hours of friction. This is a direct application of the Frontend Architecture pillar: clear boundaries and shared language.
Align naming before you align anything else. Go through the design file and the codebase together. If the same thing has different names, pick one - preferably the designer's name, since developers are better at mapping words to code than designers are at mapping code to words.
- Button, not CTAButton or ActionTrigger.
- Card, not Tile or Panel.
- Modal, not Dialog or OverlayPanel.
- If names are already mismatched, create a migration period where both names work, then deprecate the old one.
Naming Convention Explorer
Click each pair to reveal the recommended name and why it matters.
Click each pair to reveal the recommended naming convention.
Governance that does not get in the way
Light governance wins. One owner per component, clear review criteria, and a contribution template that takes ten minutes to fill.
Governance is the most common reason design systems stagnate. Too much process and nobody contributes. Too little process and the library becomes inconsistent.
The right balance is surprisingly light. One person owns each component (the "component steward"). They review contributions for API consistency, accessibility, and test coverage. The bar is: does this match our existing conventions and patterns? If yes, it ships. If not, the steward works with the contributor to align it.
The key is that the review happens fast. If a contribution sits for more than two days, the steward is the bottleneck. Rotate the role monthly to distribute knowledge and prevent burnout.
text
Component proposal template
Component name: matches design file?
Used by: at least 2 surfaces today, 3 to promote to core
API: props table; follows naming conventions?
Accessibility: keyboard nav, screen reader tested?
Tests: integration test for main workflow?
Design reference: link to FigmaGovernance dial
Click each governance style to compare the tradeoff between speed and control.
Click the governance style
The article argues for light governance, but this interactive card shows the tradeoff behind each approach.
Practical takeaway
Enough structure to protect consistency without turning every contribution into a long process.
Versioning and breaking changes
Follow semantic versioning strictly. Major version for breaking API changes. Provide codemods for every breaking change.
Nothing erodes trust in a design system faster than breaking changes without warning. A team upgrades the library and suddenly their buttons have different padding, their modals have different animations, and their cards have different shadows.
Semantic versioning is table stakes. Every breaking change (renamed prop, removed variant, changed behavior) gets a major version bump. Every addition gets a minor version. Every bug fix gets a patch.
For breaking changes, provide a codemod. A codemod is a script that automatically updates the consuming codebase. If you rename primary to filled on Button, ship a codemod that runs npx design-system codemod rename-button-variant and handles the migration in one command.
- Major: breaking API changes. Ship a codemod.
- Minor: new components, new variants, new props. Backward compatible.
- Patch: bug fixes, accessibility improvements, visual polish.
- Deprecation notice: mark old props as deprecated two minor versions before removal.
Measuring adoption (the only metric that matters)
Track the percentage of surfaces that use design system components. If adoption is below 70%, the system is not serving its users.
Adoption is the only real measure of a design system's health. You can have beautiful components, perfect accessibility, and comprehensive docs. If teams are not using them, the system has failed.
Track adoption with a simple CI check: scan the codebase for imports from the design system package versus raw Tailwind/CSS usage. Publish a dashboard. The trend line tells you more than any code review.
If adoption is below 70%, do not add more components. Go talk to the teams that are not using it. Find out why. The answer is usually one of: the API is awkward, the docs are unclear, or the contribution process is too slow.
- Import ratio: design system imports vs. custom CSS/Tailwind classes.
- Component coverage: what percentage of surfaces use at least one design system component.
- Contribution velocity: how many new components or variants were added in the last month.
- Time-to-adoption: how long it takes a new team to start using the system after onboarding.
Adoption metric explorer
Click a metric to translate the adoption advice into concrete signals.
Click a metric to judge adoption
This section turns abstract adoption advice into something visual and inspectable.
What to read from it
Beginner signal: are people reaching for the shared package first?
Need help implementing this?
I build these systems for a living - let's work on yours.
Product-Focused UI Engineering
Figma and specs to production. Accessible, consistent components and design-system alignment so what ships matches design and works for everyone.
Frontend Architecture & System Design
Structure so teams can ship. Clear boundaries, state strategy, and contracts. New features land cleanly; refactors stay low-risk.
Frontend Development
Production UIs in React, Next.js, or Vue- third-party and payment integrations included. Built for real traffic and maintained in production.
Your turn
- >Did this help you ship something?
- >Which part clicked the most for you?
- >Applying this at work? Share your experience.
Recommended blogs
Continue reading

How to Build an MCP Server from Scratch (Step-by-Step for Beginners)
A practical beginner guide to building a local MCP server (stdio) step-by-step. You will run a working server, connect it to Claude Desktop, and call your first tool.
Photo by Christina Morillo on Pexels
Read article
Shipping React UI Fast Without Making a Mess
The way I structure React and Next.js UI so the team ships fast because the system is obvious, not because we skipped every guardrail.
Photo by Zak Chapman on Pexels
Read article
Discussion
Leave a comment
Thoughts, questions, corrections - all welcome.