Systematic thinking for design systems

Design systems thrive on systematic principles, not just a growing list of components.


In this article

Design systems have become the holy grail of product design — every team wants one, most teams build one, and many teams end up with dozens of components and endless variations that need maintaining.

On the surface, everything looks consistent. The branding matches, the spacing feels similar, the colours align. But underneath, duplicated code with minor differences mounts up — creating maintenance costs, unnecessary bloat, and a system that becomes harder to update as time goes on.

The real cost appears when something new is needed. Without established systematic principles, it’s tempting to design another component variation instead of using what exists. Component libraries can grow exponentially whilst core design languages stay shallow. The goal becomes having fewer, better components — not more variations that serve similar purposes.

Most design systems start by creating components. Teams design buttons, inputs, cards, modals — each carefully crafted and documented. The focus goes to component APIs, props, variants, and usage guidelines. Documentation showcases different button types, input configurations, and card layouts.

This feels productive. The component library grows. The Storybook fills up. Designers have Figma files full of components. But something’s missing.

The problem isn’t the components themselves — it’s that we’re designing them without establishing the systematic principles that should generate them. Each component gets designed in isolation, solving its immediate use case without considering how its patterns relate to everything else in the system.

Systematic design inverts the component-first approach. Instead of designing components and hoping consistency emerges, we establish principles and formulas that determine how everything should behave. Components become expressions of these principles rather than individual design decisions.

Consider what needs to be systematic:

Interaction states: How does hover work across the entire system? What about focus, active, disabled? When something is clickable versus static, what visual language distinguishes them? These patterns shouldn’t vary by component — they should be systematic principles that every interactive element follows.

Message tones: How do we communicate positive, negative, neutral, and warning states? These aren’t just alert component colours — they’re systematic approaches to colour, weight, and styling that should appear consistently across validation states, status indicators, and informational messaging.

Spacing relationships: What’s the rhythm between text elements, between form sections, between page sections? These relationships shouldn’t get decided component by component — they should be systematic scales that components inherit automatically.

Typography hierarchy: How do headings, body text, labels, and captions relate to each other? This hierarchy should be systematic, not redefined for each component context.

When these principles are systematic, components almost design themselves. By the time you need a new button, card, or input, the interaction patterns, colour applications, spacing rhythms, and typography scales have already determined most of the design. You’re not making component decisions — you’re expressing systematic principles.

Without systematic thinking, similar-looking UI elements can behave completely differently. Interactive elements might look identical to static decoration. Hover states might work one way on buttons and another way on cards. Focus indicators might appear inconsistently. Validation states might use different visual languages across forms.

These inconsistencies aren’t obvious when designing components in isolation. Each component looks fine on its own. The problem only becomes apparent when users encounter multiple components in the same interface and can’t predict how they’ll behave.

The maintenance cost is even less visible. When every component embeds its own approach to interaction states, spacing, and styling, updating anything systematic requires touching dozens of components. Want to adjust how hover states work? Now you’re modifying every interactive component individually rather than updating one systematic principle.

When a new use case doesn’t fit existing components, the component-first instinct is to create a new variant. Need a card with different padding? Create a new card type. Need a button that looks slightly different? Add another button variant. Need to display information in a new format? Build a new component.

Each decision feels pragmatic in isolation — we’re just solving the immediate problem. But this is how component libraries grow to 20+ button variations, multiple card types that differ only in padding values, and duplicated banner components that vary only in background colour.

The systematic approach asks different questions: Why doesn’t our existing card support this padding? Can we adjust our spacing principles to accommodate this need? Does this really need a new component, or can we extend systematic principles to cover this case?

Sometimes the answer genuinely is “we need a new component.” But often, we’re working around inadequate systematic principles rather than fixing them. The fix isn’t creating a new component — it’s going back to the systematic level and adjusting the principles so existing components can handle the use case.

The most effective design systems we’ve worked with treat components as outputs rather than foundations. The real system lives in the principles, formulas, and relationships that generate consistent experiences automatically.

Documentation shifts from showcasing component variations to explaining systematic principles. Instead of “here’s how our 15 button types work,” it becomes “here’s how interaction states work systematically, and here’s how buttons express those principles.”

New team members learn the systematic patterns once and can predict how components should behave. Developers implement new components without detailed specifications because the systematic principles already document the decisions. The component library stabilises because systematic thinking handles edge cases without requiring new variants.

If component libraries keep growing whilst consistency stays elusive, the fix starts with systematic principles rather than better component documentation.

Pick one pattern area — interaction states, message tones, or spacing relationships. Document the principles behind how these currently work, identify where different components handle them inconsistently, and establish systematic approaches that should apply everywhere.

Then apply these principles without exception. When a new case doesn’t fit, adjust the systematic principle rather than creating a component-specific exception. This feels slower initially — it’s easier to just create a new variant. But it’s the difference between a component library that grows forever and a design system that actually works systematically.

The goal isn’t comprehensive component coverage. It’s systematic principles that make most component decisions inevitable rather than arbitrary.