Designing with Layers
A systems approach to component architecture that anticipates complexity before it manifests in code.
The Problem with Flat Component Libraries
When design systems first take root, they begin with components: buttons, inputs, icons, toggles. The goal is consistency, but consistency alone doesn't explain why complexity creeps in. Over time, you notice the neat catalog breaks down: forms behave differently across contexts, toolbars overflow with actions, editors sprout feature walk-throughs, and pagination mutates with ellipses and compact modes.
The problem isn't that your system is "messy." The problem is that you're seeing composition at work. Complexity in digital interfaces rarely comes from primitives themselves—it emerges when small parts are combined, orchestrated, and pushed against application workflows.
To build systems that endure, you need a lens that helps you anticipate this layering before it manifests in code. That's what the layered component methodology provides: a way to classify, compose, and govern components across four levels of scale.
The Four Layers
Each layer represents a different level of complexity, responsibility, and governance. Understanding where a component belongs helps teams make better decisions about APIs, ownership, and extensibility.
Primitives
The boring building blocks that make everything else possible.
Irreducible components like buttons, inputs, checkboxes, and icons. Their goals are stability, accessibility, and consistency. They should be as "boring" as possible.
- Examples
- Button, Input, Checkbox, Icon, Typography
- Work of the System
- Naming, tokens, accessibility patterns
- Watch for
- Bloated props, reinventing label or error logic
Deep dive into Primitives
Compounds
Blessed combinations with baked-in conventions.
Compounds bundle primitives into predictable, reusable groupings. They codify conventions and reduce repeated decision-making across teams.
- Examples
- TextField, Card, TableRow, Chip, Avatar
- Work of the System
- Defining which sub-parts exist, providing safe variations
- Watch for
- "Mega-props" that account for every variation
Deep dive into Compounds
Composers
Orchestration of state, interaction, and context.
Composers orchestrate state, focus, and behavior across multiple children. This is where systems meet complexity: modals, toolbars, message composers, pagination.
- Examples
- Modal, FormField, Toolbar, Pagination, Rich Text Editor
- Work of the System
- Governing orchestration, exposing slots, avoiding prop explosion
- Watch for
- Burying orchestration in ad-hoc props instead of context
Deep dive into Composers
Assemblies
Product-level flows that live outside the system.
Assemblies are application-specific flows encoded as components. They aren't universal system primitives; they're product constructs that use the system's building blocks.
- Examples
- Checkout Flow, Project Board, Analytics Dashboard
- Work of the System
- Provide building blocks; assemblies live at the app layer
- Watch for
- Accidentally "baking in" product-specific flows
Deep dive into Assemblies
Why Composition Matters
Design systems cannot anticipate every product problem, every variant, or every edge case. If they try, they either collapse under prop bloat ("yet another boolean for yet another exception") or grind to a halt as every new request funnels through the system team. Both outcomes slow teams and erode trust.
Composition is the release valve. By leaning into patterns like compound components, slotting, and substitution, you give product teams a way to:
- Use the system a la carte: Pull in primitives and compounds without committing to a rigid, monolithic API.
- Insert what they need: Slot in custom behavior, add a product-specific sub-control, or override presentation while still sitting inside the system's orchestrator.
- Omit what they don't: Drop optional slots or props that aren't relevant, without violating conventions.
- Stay unblocked: Product timelines aren't gated by triage queues; teams compose from known parts and keep shipping.
- Adhere where possible: Because orchestration is handled by composers, accessibility, ARIA, and state management rules are inherited "for free."
This is why composition is a governance strategy, not just a coding trick. It creates a continuum: the system team defines boundaries and patterns, and product teams compose solutions inside those boundaries without waiting for new one-off components.
Meta-Patterns Across All Layers
Regardless of layer, three meta-patterns ensure scalability and prevent system collapse under exceptions:
- Slotting & Substitution
- Anticipate replaceable regions (children, slots, render props). This allows product teams to customize without forking. The system defines the shape; teams fill in the content.
- Headless Abstractions
- Separate logic (hooks, providers) from presentation (styled components). This enables theming, testing, and platform-specific implementations without duplicating behavior.
- Contextual Orchestration
- Treat composers as state providers, not just visual containers. Context APIs share state between sub-parts without prop drilling, making complex interactions manageable.
These aren't just coding tricks—they're governance strategies. They help a design system resist collapse under exceptions.
Thinking in Layers
For junior designers, the natural unit of thinking is the screen: what needs to be drawn to make this flow work? For system designers, the unit shifts to grammar: what are the rules of combination, and how do we prepare for emergent complexity?
| Layer | Demand | Focus |
|---|---|---|
| Primitives | Standards | Stability, tokens, accessibility |
| Compounds | Conventions | Blessed combinations, consistent spacing |
| Composers | Orchestration | State management, focus, context |
| Assemblies | Boundaries | Product-specific flows, business logic |
When you apply this layered lens, your system stops being a library of parts and becomes a language for products.
Complexity is Inevitable. Chaos is Optional.
The goal isn't to eliminate complexity—it's to channel it into structures that remain legible, maintainable, and extensible. Composition makes that channel possible:
- A button is stable.
- A field is orchestrated.
- A toolbar overflows gracefully.
- A rich text editor governs the chaos of paste and plugins.
And crucially: when product teams need something new, they don't need to break the system—they compose with it.
By recognizing components not as flat things, but as layered patterns, you prepare your system for growth. You teach teams not only what to build, but how to think about building—and that's the difference between a component library and a true design system.