Radix UI
01 / 02

Radix UI Fundamentals: Compound Components & Accessibility

Radix UI: Compound Components & Accessibility

Radix UI is an unstyled, accessible component library for React. It provides correct behavior, state management, and full WAI-ARIA-compliant accessibility for hard-to-build UI patterns -- dialogs, dropdowns, tooltips, selects -- while leaving all visual styling entirely to the consumer.

Compound Component Structure

import * as Dialog from '@radix-ui/react-dialog'

function ConfirmDialog() {
  return (
    <Dialog.Root>
      <Dialog.Trigger className="btn">Delete item</Dialog.Trigger>
      <Dialog.Portal>
        <Dialog.Overlay className="overlay" />
        <Dialog.Content className="dialog-content">
          <Dialog.Title>Are you sure?</Dialog.Title>
          <Dialog.Description>This cannot be undone.</Dialog.Description>
          <Dialog.Close className="btn-secondary">Cancel</Dialog.Close>
          <button onClick={handleDelete}>Confirm</button>
        </Dialog.Content>
      </Dialog.Portal>
    </Dialog.Root>
  )
}

Root holds shared state (open/closed) via React context, so nested pieces like Trigger and Close coordinate without prop-drilling. Each piece -- Trigger, Content, Close -- owns one responsibility, giving fine-grained control over markup structure that a single monolithic component with dozens of props would make awkward.

asChild: Merging Behavior onto Your Own Elements

// Without asChild: Trigger renders its own default <button>,
// wrapping MyCustomButton inside it -- invalid nested-button markup
<Dialog.Trigger><MyCustomButton>Open</MyCustomButton></Dialog.Trigger>

// With asChild: Radix merges its click handlers/ARIA attributes
// directly onto MyCustomButton, with no extra wrapping element
<Dialog.Trigger asChild>
  <MyCustomButton>Open</MyCustomButton>
</Dialog.Trigger>

Accessibility Handled Automatically

  • Focus trapping inside an open Dialog (Tab/Shift+Tab cycles only through its contents) and focus restoration to the trigger on close.

  • Full keyboard navigation for menus/selects -- arrow keys between items, Enter/Space to select, Escape to close, and typeahead.

  • Correct ARIA roles/attributes and screen reader announcements for every interactive pattern.

  • Portal (e.g. Dialog.Portal) renders overlay content near document.body, avoiding clipping by an ancestor's overflow:hidden or z-index stacking context.

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free