Headless Component Libraries
How modern React teams build accessible, fully custom design systems without reinventing complex UI logic like focus trapping or keyboard navigation.
Behavior Without Style
Historically, component libraries like Bootstrap or Material UI gave you both behavior *and* styling. But overriding their default styles to match your company's unique brand design was a massive headache.
**Headless UI libraries** (like Radix Primitives, React Aria, or HeadlessUI) do the exact opposite. They provide 100% of the complex logic, accessibility (ARIA attributes), and state management, but **zero styling**.
The Accessibility Burden
Building a simple <button> is easy. Building a custom accessible <DropdownMenu> or <Dialog> modal is incredibly difficult.
You have to manage focus trapping, aria-expanded attributes, closing on 'Escape', closing on outside clicks, and screen reader announcements.
Headless components solve this by providing invisible "wrapper" components that handle all the W3C accessibility standards, leaving you free to just paint them with CSS or Tailwind.
Composing Headless Components
Instead of a single <Dropdown /> tag, headless libraries usually provide a set of composable parts:
<Menu> (the state provider)
<Menu.Button> (the trigger that toggles the menu)
<Menu.Items> (the container for the list, handles focus trapping)
<Menu.Item> (the individual choices, handles arrow key navigation)
The Skeleton vs The Skin
Interact with the headless Dialog below. Toggle between 'Unstyled' (the raw headless logic) and 'Tailwind Styled'. Notice that the core behavior (opening, closing, clicking outside) works perfectly in both, but the styling is entirely up to you.
<Dialog.Trigger>Open</Dialog.Trigger>
<Dialog.Content>...</Dialog.Content>
</Dialog.Root>
className="fixed z-50 bg-white rounded-xl shadow-2xl p-6"
>...</Dialog.Content>
Click the button below. Then try closing the modal by clicking outside it or pressing the Escape key.
Toggle between 'Unstyled' and 'Styled'. The core headless logic (closing on Escape or outside click) is identical. Headless UI provides the skeleton; you provide the skin.
Check yourself
Pick an answer to lock it in, then read why. Getting one wrong is part of how it sticks.
Remember this
- Headless UI libraries provide behavior and accessibility, but no styles.
- They solve the massive headache of overriding traditional component libraries.
- They handle complex W3C standards like focus trapping and ARIA attributes for you.
- You compose them using multi-part components (e.g., Menu, Menu.Button, Menu.Items).
- shadcn/ui is a popular pattern of wrapping headless primitives with Tailwind classes in your own codebase.
Done with this concept?
Mark it complete to track your progress. No login needed.