Component libraries and UI infrastructure
The UI kit: primitives, styles, and interactions
A UI kit stays composable when it separates presentational primitives from headless interaction behaviors instead of shipping monolithic all-in-one widgets.
A design system establishes visual language and interaction rules. The UI kit is where those decisions become executable code.
Without a shared kit, teams face an unfair dilemma every sprint: hand-craft accessible HTML controls from scratch under delivery pressure, or import heavy third-party packages with conflicting styling engines. Controls look deceptively simple until we account for focus order, keyboard roving indices, high-contrast states, and responsive edge cases. Absorbing that baseline complexity once is the kit's primary job. It provides dependable, composable primitives so our engineering teams can move fast without sacrificing accessibility.
The three layers of a kit
A durable UI kit divides along responsibility lines:
- Visual primitives: Presentational components like
Button,Input,Surface, andBadge. They consume design tokens for color, typography, spacing, and elevation. Crucially, they preserve native HTML mechanics, including tab order, disabled states, and form submission, rather than burying them under custom wrappers. - Interaction behaviors: Headless mechanics that native HTML does not provide natively: focus management, keyboard roving indices, typeahead selection, and overlay positioning.
- Composite controls: Composed patterns like a
DatePickerorConfirmDialogthat assemble primitives and behaviors into common configurations to save our teams from reinventing tricky interactions.
Composite control
AlertDialog
Visual primitives
Surface · Heading · Button
Headless behavior
DialogBehavior · Focus · Escape
Foundation
Design tokens + native HTML
The tension in most component libraries comes from collapsing these layers into monolithic widgets. When a library only exports a rigid <FilterDropdown />, the first product team that needs a custom badge inside the menu option may end up forking the entire component.
Decouple behavior from markup
Interactive components change for different reasons. Visual styling shifts with brand and design polish, while selection rules, focus management, and keyboard navigation evolve with interaction requirements.
Take multi-item selection. A behavior can own the selected IDs and the operations that change them, without deciding how a selected item looks:
interface SelectionBehavior<Id> {
selectedIds: ReadonlySet<Id>;
toggle(id: Id): void;
clear(): void;
}
A file table and an image grid can use the same selection behavior while rendering their items differently. Each still needs the appropriate HTML semantics and keyboard interaction for its own UI; this contract only handles selection state. Changing how selection works does not require changing either visual layout.
Composite controls are thin assemblies
Composite controls should be conveniences rather than walled gardens. When our kit ships an AlertDialog, it packages an underlying DialogBehavior, Surface, Heading, and Button into a sensible default.
The critical architectural discipline is ensuring that assembling composite controls does not hide the underlying pieces. The kit must export each primitive and behavior independently. Later chapters examine how component APIs preserve those boundaries as requirements grow, and how teams can extend them cleanly when a product workflow outgrows the default configuration.
A UI kit succeeds when standard interfaces are effortless to assemble and advanced patterns build directly on the same tested foundations. When primitives, styles, and behaviors each have a dedicated home, delivery velocity stays high across the entire product.