Back to System Design
System Design
easy
mid

What reusable components or patterns would you build for a long lived design system?

Build a layered set: design-system primitives (Button, Input, Modal, Toast), composite components (DataTable, Form, Dropdown), layout primitives (Stack, Grid), and behavioral patterns/hooks (useDisclosure, compound components, render props). Reusability comes from good APIs, not just existence.

6 min read·~12 min to think through

"Reusable" isn't about quantity — it's about a layered library with clean, composable APIs that the team actually reaches for instead of rebuilding.

Layer 1 — Design-system primitives

The atoms every screen needs:

  • Button (variants, sizes, loading, icon slots), Input, Select, Checkbox, Radio, Textarea
  • Modal/Dialog, Drawer, Popover, Tooltip
  • Toast/Notification, Badge, Avatar, Spinner, Skeleton
  • Card, Tabs, Accordion

All consume design tokens, are fully accessible, and support controlled/uncontrolled use.

Layer 2 — Layout primitives

Composition tools that kill one-off CSS:

  • Stack / HStack / VStack (gap-based spacing)
  • Grid, Box, Container, Spacer, Divider

Layer 3 — Composite / domain components

Built from primitives, encapsulating real complexity:

  • DataTable (sort, filter, paginate, select, virtualize)
  • Form + FormField (validation, error display, layout)
  • Dropdown/Combobox (search, multi-select, async options)
  • DatePicker, FileUpload, Pagination, SearchBar, EmptyState, ErrorState

Layer 4 — Behavioral patterns (the reusable logic)

Often more valuable than components:

  • Custom hooksuseDisclosure, useDebounce, usePagination, useClickOutside, useMediaQuery
  • Compound components<Tabs><Tabs.Tab/></Tabs> for flexible structure
  • Render props / headless components — logic without markup (à la Radix/Headless UI), so teams style freely
  • Provider patternsThemeProvider, ToastProvider, AuthProvider
  • HOCs / wrapperswithErrorBoundary, withAuth (used sparingly)

What makes them actually reusable

  • Good API design — minimal props, sensible defaults, composable, follows native conventions (value/onChange).
  • Headless where it helps — separate behavior from styling so the component survives redesigns.
  • Accessible by default — keyboard, ARIA, focus management baked in.
  • Documented — Storybook with examples; otherwise people rebuild it.
  • Themeable via tokens, not hardcoded.
  • Don't over-abstract — a component used once with five variant props is worse than two simple components.

The meta-point

Reusability is an API design discipline. A component nobody can figure out gets copy-pasted and forked. Build the primitives well, document them, and the composites fall out naturally.

Follow-up questions

  • What separates a genuinely reusable component from one that just exists?
  • What are headless components and why are they powerful?
  • When does abstracting for reuse backfire?
  • How do compound components improve a component's API?

Common mistakes

  • Equating 'lots of components' with 'good reusability'.
  • Over-abstracting — one component with a dozen variant props.
  • Skipping accessibility, so the primitives can't safely be used everywhere.
  • No documentation/Storybook, so people rebuild instead of reuse.

Performance considerations

  • Well-bounded primitives memoize cleanly and code-split well. Headless components let consumers control render cost. A bloated mega-component with many props often re-renders more than two focused ones.

Edge cases

  • A component needed in two places that are subtly different — abstract or duplicate?
  • Primitives that need to escape their own styling for one consumer.
  • Versioning a shared library without breaking consumers.
  • Third-party components that don't fit the token system.

Real-world examples

  • Radix UI / Headless UI (headless behavioral primitives) + a styled layer on top.
  • An internal design system: tokens → primitives → composites → Storybook docs.

Senior engineer discussion

Seniors answer in layers (primitives → layout → composites → behavioral patterns/hooks) and stress that reusability is API-design discipline, not component count. They bring up headless components for surviving redesigns, accessibility-by-default, Storybook as adoption infrastructure, and the over-abstraction trap — duplication can beat the wrong abstraction.

Related questions