component
Component Architecture Patterns
Build accessible, headless UI components using proven patterns from Base UI, Radix, and Ark UI. These patterns are framework-agnostic — core concepts apply across React, Vue, Svelte, Solid, and vanilla JS.
Primary sources:
- Base UI Handbook
- Ark UI — Cross-framework implementation
- Zag.js — State machines for UI components
Framework-specific: react.md | html.md
Core Principles
- Headless over styled — Separate behavior from presentation
- Compound over monolithic — Small composable parts over config-heavy megacomponents
- Controlled + uncontrolled — Support both state ownership models
- Accessible by default — ARIA, keyboard nav, focus management built-in
- State via attributes — Expose state through
data-*for framework-agnostic styling
Pattern 1: Compound Components
What: Components as related parts sharing state through context, each mapping 1:1 to DOM elements.
Why:
- Declarative — assemble like building blocks, reorder/omit parts freely
- Each part is an independent styling target
- DOM structure maps directly to ARIA roles
Standard hierarchies:
| Type | Parts |
|---|---|
| Popups | Root → Trigger → Portal → Positioner → Popup → Arrow |
| Collections | Root → List → Trigger + Panel |
| Forms | Root → Label → Control → Description → Error |
Ref: Base UI Composition
Pattern 2: Controlled & Uncontrolled State
What: Support external state control OR internal state with consistent prop naming.
Why:
- Flexibility for simple and complex use cases
- Predictable API across components
- Change details enable fine-grained control (cancel changes, track reasons)
Convention:
| State | Uncontrolled | Controlled | Handler |
|---|---|---|---|
| Open | defaultOpen |
open |
onOpenChange(open, details) |
| Value | defaultValue |
value |
onValueChange(value, details) |
| Checked | defaultChecked |
checked |
onCheckedChange(checked, details) |
Change details: { reason, event, cancel() }
Pattern 3: Prop Getters
What: Functions returning HTML attributes for DOM elements, abstracting logic from rendering.
Why:
- Portable across frameworks (React, Vue, Svelte, Solid)
- Clean separation of concerns
- Composable via
mergeProps()
Example: getTriggerProps() returns { aria-expanded, aria-haspopup, onClick, onKeyDown }
Pattern 4: State via Data Attributes
What: Expose state through data-* attributes for CSS targeting.
Why:
- Framework-agnostic styling
- No JS needed for state-based styles
- Inspectable in DevTools
Standard attributes:
data-open/data-closed— Visibilitydata-checked/data-unchecked— Toggle statedata-highlighted— Focus within groupdata-disabled,data-valid,data-invaliddata-side,data-align— Positioning
CSS variables: --available-height, --anchor-width, --transform-origin
Ref: Base UI Styling
Pattern 5: Accessibility
What: ARIA, keyboard navigation, focus management built into architecture.
Why:
- Accessibility is structural, not decorative
- Users expect standard keyboard interactions
- Consistent patterns reduce errors
Key concerns:
- ARIA attributes — Auto-managed from state
- Focus trapping — Modals trap focus within
- Roving tabindex — One tabbable item, arrows navigate
- Virtual focus —
aria-activedescendantfor long lists - Typeahead — A-Z jumps to matches
Ref: Base UI Accessibility, WAI-ARIA Practices
For detailed accessibility patterns, load the aria skill.
Pattern 6: Floating Positioning
What: Position popups relative to triggers with collision detection.
Why: Handles viewport boundaries, scroll, resize automatically.
Config: side, align, sideOffset, collision (flip/shift), trackAnchor
Ref: Floating UI
API Conventions
| Category | Props |
|---|---|
| Interaction | disabled, required, readOnly |
| Collections | multiple, loopFocus, orientation |
| Popups | modal, closeOnEscape, closeOnOutsideClick, keepMounted |
| Positioning | side, align, sideOffset, collision |
Imperative actions: actionsRef exposing open(), close(), toggle()
See props.md for naming conventions.
Reference Files
| File | Contents |
|---|---|
| html.md | HTML controllers, mixins, context |
| videojs-element.md | ReactiveElement lifecycle, properties, controllers |
| react.md | React hooks, context, refs |
| props.md | Prop naming, conventions, defaults |
| styling.md | Data attributes, CSS variables |
| animation.md | CSS transitions, JS animation libs |
| polymorphism.md | render vs asChild patterns |
| collection.md | Collections, portals, virtualization |
| anti-patterns.md | Common component mistakes |
| videojs.md | Video.js component architecture |
For accessibility patterns (ARIA, keyboard, focus), load the aria skill.
Review
For structured component reviews, load the review workflow:
| File | Contents |
|---|---|
| workflow.md | Review process and severity |
| checklist.md | Component review checklist |
| templates.md | Issue and report formats |
Implementation Sources
| Resource | Use For |
|---|---|
| Base UI Source | React reference implementations |
| Radix Primitives | Alternative approach |
| Zag.js | Framework-agnostic state machines |
| Floating UI | Positioning |
Related Skills
| Need | Use |
|---|---|
| Accessibility patterns | aria skill |
| API design principles | api skill |
| Documentation patterns | docs skill |
| Component API reference | api-reference skill |