Build accessible, headless UI components with modern architecture patterns. Use when creating component libraries, design systems, or reusable UI primitives...
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:
Framework-specific: react.md | html.md
data-* for framework-agnostic stylingWhat: Components as related parts sharing state through context, each mapping 1:1 to DOM elements.
Why:
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
What: Support external state control OR internal state with consistent prop naming.
Why:
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() }
What: Functions returning HTML attributes for DOM elements, abstracting logic from rendering.
Why:
mergeProps()Example: getTriggerProps() returns { aria-expanded, aria-haspopup, onClick, onKeyDown }
What: Expose state through data-* attributes for CSS targeting.
Why:
Standard attributes:
data-open / data-closed — Visibilitydata-checked / data-unchecked — Toggle statedata-highlighted — Focus within groupdata-disabled, data-valid, data-invaliddata-side, data-align — PositioningCSS variables: --available-height, --anchor-width, --transform-origin
Ref: Base UI Styling
What: ARIA, keyboard navigation, focus management built into architecture.
Why:
Key concerns:
aria-activedescendant for long listsRef: Base UI Accessibility, WAI-ARIA Practices
For detailed accessibility patterns, load the aria skill.
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
| 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.
| 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.
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 |
| Resource | Use For |
|---|---|
| Base UI Source | React reference implementations |
| Radix Primitives | Alternative approach |
| Zag.js | Framework-agnostic state machines |
| Floating UI | Positioning |
| Need | Use |
|---|---|
| Accessibility patterns | aria skill |
| API design principles | api skill |
| Documentation patterns | docs skill |
| Component API reference | api-reference skill |