Base UI Guide
Base UI (@base-ui/react) is an unstyled React component library for building accessible user interfaces. From the creators of Radix, Material UI, and Floating UI. Components are headless, composable, and WAI-ARIA compliant. Supports React 17+ and all modern browsers (Baseline Widely Available). Tree-shakable single package.
Do NOT use this guide for Radix UI (radix-ui), Material UI (MUI @mui/material), or Shadcn/ui — those are separate libraries with different APIs.
Quick Start
npm i @base-ui/react
Setup
- Portals - Add stacking context isolation to prevent z-index conflicts:
.root { isolation: isolate; }
<body><div className="root">{children}</div></body>
- iOS 26+ Safari - For dialog backdrops:
body { position: relative; }
Import Pattern
All components use namespaced compound pattern from a single package:
import { Popover } from '@base-ui/react/popover';
<Popover.Root>
<Popover.Trigger>Open</Popover.Trigger>
<Popover.Portal>
<Popover.Positioner sideOffset={8}>
<Popover.Popup>
<Popover.Arrow />
<Popover.Title>Title</Popover.Title>
<Popover.Description>Content</Popover.Description>
</Popover.Popup>
</Popover.Positioner>
</Popover.Portal>
</Popover.Root>
Core Patterns
Styling (components are completely unstyled)
CSS Classes - static or state-dependent:
<Switch.Thumb className="SwitchThumb" />
<Switch.Thumb className={(state) => state.checked ? 'checked' : 'unchecked'} />
Data Attributes - all components expose state via data-* attributes:
.SwitchThumb[data-checked] { background: blue; }
.Popup[data-starting-style] { opacity: 0; transform: scale(0.9); }
CSS Custom Properties - dynamic values for layout/animation:
.Indicator { width: var(--slider-indicator-width); }
.Popup { transform-origin: var(--transform-origin); }
Works with Tailwind CSS, CSS Modules, CSS-in-JS, or plain CSS.
Composition (render prop)
Replace default elements with custom components or different HTML tags:
// Custom component (must forward ref and spread props)
<Dialog.Trigger render={<MyButton size="md" />} />
// Different HTML element
<Menu.Item render={<a href="/profile" />}>Profile</Menu.Item>
// Render function with state access
<Checkbox.Root render={(props, state) => (
<span {...props}>{state.checked ? <CheckIcon /> : <BoxIcon />}</span>
)} />
Server Components (Next.js / RSC)
All interactive Base UI components require 'use client' in React Server Component environments. Only static display components (Separator, Avatar without interaction) can be used in server components.
Combobox List Render Pattern
Combobox and Autocomplete use a unique render-children pattern on List — pass a function that receives each filtered item:
<Combobox.List>
{(item) => (
<Combobox.Item key={item.value} value={item}>
{item.label}
</Combobox.Item>
)}
</Combobox.List>
This differs from Select, where you explicitly .map() over items inside Select.List.
Controlled vs Uncontrolled
All interactive components support both modes:
// Uncontrolled (internal state)
<Dialog.Root defaultOpen={false}>
// Controlled (external state)
<Dialog.Root open={isOpen}
Event Customization
Change handlers receive (value, eventDetails):
<Dialog.Root details) => {
if (details.reason === 'escape-key') {
details.cancel(); // Prevent closing
}
}}>
Key eventDetails methods: cancel(), allowPropagation(). Access reason for why the change occurred.
Animation
CSS Transitions (recommended - can be cancelled midway):
.Popup {
transition: transform 150ms, opacity 150ms;
transform-origin: var(--transform-origin);
}
.Popup[data-starting-style],
.Popup[data-ending-style] {
opacity: 0;
transform: scale(0.9);
}
CSS Animations: Use [data-open] / [data-closed] with @keyframes.
JavaScript (Motion): Use keepMounted + render prop + <AnimatePresence>.
TypeScript
Types organized by namespace:
Tooltip.Root.Props // Component props
Popover.Positioner.State // Internal state type
Combobox.Root.ChangeEventDetails // Event details type
Component Catalog
Overlay & Navigation
| Component |
Parts |
Description |
| Dialog |
Root, Trigger, Portal, Backdrop, Popup, Title, Description, Close |
Modal dialog with focus trap |
| AlertDialog |
Root, Trigger, Portal, Backdrop, Popup, Title, Description, Close |
Confirmation dialog (no pointer dismiss) |
| Popover |
Root, Trigger, Portal, Positioner, Popup, Arrow, Title, Description |
Non-modal floating content |
| Tooltip |
Provider, Root, Trigger, Portal, Positioner, Popup, Arrow |
Hover/focus info popup |
| PreviewCard |
Root, Trigger, Portal, Positioner, Popup, Arrow |
Link hover preview |
| Toast |
Provider, Portal, Viewport, Root, Title, Description, Action, Close |
Notification toasts (stacked or anchored) |
| Menu |
Root, Trigger, Portal, Positioner, Popup, Arrow, Item, Group, Separator + Radio/Checkbox items |
Dropdown menu with submenus |
| ContextMenu |
Root, Trigger, Portal, Positioner, Popup, Item, Group + submenus |
Right-click context menu |
| NavigationMenu |
Root, List, Item, Trigger, Content, Portal, Positioner, Popup, Link |
Site navigation with panels |
| Menubar |
Wrapper + Menu.Root instances |
Horizontal application menu bar |
Form Controls
| Component |
Parts |
Description |
| Form |
Single wrapper |
Form with validation and submission |
| Field |
Root, Label, Control, Description, Error, Validity |
Field wrapper with validation |
| Fieldset |
Root, Legend |
Groups related fields |
| Input |
Single element |
Text input with state data attributes |
| NumberField |
Root, ScrubArea, Group, Decrement, Input, Increment |
Numeric input with stepper |
| Checkbox |
Root, Indicator |
Checkbox with indeterminate support |
| CheckboxGroup |
Root |
Manages multiple checkbox state |
| Radio |
Root, Indicator + RadioGroup |
Radio button group |
| Select |
Root, Trigger, Value, Portal, Positioner, Popup, List, Item, ItemIndicator |
Dropdown select |
| Combobox |
Root, Input, Trigger, Portal, Positioner, Popup, List, Item + chips |
Searchable select with filtering |
| Autocomplete |
Root, Input, Trigger, Portal, Positioner, Popup, List, Item |
Text input with suggestions |
| Switch |
Root, Thumb |
Toggle switch |
| Slider |
Root, Value, Control, Track, Indicator, Thumb |
Range slider (single or multi-thumb) |
| Toggle |
Single element |
Pressable toggle button |
| ToggleGroup |
Wrapper + Toggle children |
Exclusive or multi-select toggles |
| Button |
Single element |
Accessible button |
Display & Layout
| Component |
Parts |
Description |
| Accordion |
Root, Item, Header, Trigger, Panel |
Expandable content sections |
| Collapsible |
Root, Trigger, Panel |
Single expand/collapse |
| Tabs |
Root, List, Tab, Indicator, Panel |
Tabbed interface |
| ScrollArea |
Root, Viewport, Content, Scrollbar, Thumb, Corner |
Custom scrollbars |
| Toolbar |
Root, Button, Link, Separator, Group, Input |
Action toolbar |
| Separator |
Single element |
Visual divider |
| Progress |
Root, Track, Indicator, Value, Label |
Progress bar |
| Meter |
Root, Track, Indicator, Value, Label |
Gauge/meter display |
| Avatar |
Root, Image, Fallback |
Profile image with fallback |
Utilities
| Utility |
Purpose |
| CSPProvider |
Apply nonce to inline styles/scripts for CSP |
| DirectionProvider |
Enable RTL behavior for components |
| mergeProps |
Merge React props with special handler/class/style merging |
| useRender |
Hook to enable render prop pattern in custom components |
Key Rules
- Always use
isolation: isolate on app root for portal z-index stacking
- Components are unstyled - you must provide all CSS
- Custom components in
render must forward ref and spread props
- Use data attributes for state-based styling, not className toggling
- CSS transitions > CSS animations for interruptible open/close effects
- Animate opacity (even 0.9999) so Base UI detects animation completion before unmounting
- Form fields need
name prop on Field.Root for form submission
- Field.Label uses
nativeLabel prop - set false for button-based controls (Select, Combobox)
- Popup components follow: Root > Trigger > Portal > Positioner > Popup > Arrow pattern
preventBaseUIHandler() on React events to bypass Base UI's internal event handling
Common Pitfalls
- Portal z-index issues: Forgot
isolation: isolate on app root - popups appear behind content
- Animation not completing: Not animating
opacity - Base UI uses element.getAnimations() to detect completion; animate opacity even to 0.9999 if not otherwise needed
- Select/Combobox label not associating: Need
nativeLabel={false} on Field.Label for button-based controls (Select, Combobox)
- Popup appearing behind content: Missing
Portal wrapper or stacking context not set up
- Form values not collected on submit: Missing
name prop on Field.Root
- Nested popups all close on Esc: Default behavior stops propagation; use
eventDetails.allowPropagation() if you want parent popups to also close
- Motion exit animations not playing: Must use
keepMounted on Portal + controlled open state + <AnimatePresence> for unmounted components
Common CSS Variables
Popup/floating components expose:
--anchor-width, --anchor-height - Trigger element dimensions
--available-width, --available-height - Available space
--transform-origin - Animation origin point
Sizing components expose:
--accordion-panel-height, --collapsible-panel-height - Panel dimensions
--slider-*, --scroll-area-* - Component-specific sizing
--active-tab-left, --active-tab-width - Tab indicator positioning
Reference Files
references/components-dialogs.md - Dialog, AlertDialog, Popover, Tooltip, PreviewCard
references/components-menus.md - Toast, Menu, ContextMenu, NavigationMenu, Menubar, shared patterns
references/components-form-fields.md - Form, Field, Fieldset, Input, NumberField, Checkbox, CheckboxGroup, Radio
references/components-form-controls.md - Select, Combobox, Autocomplete, Switch, Slider, Toggle, ToggleGroup, Button
references/components-panels.md - Accordion, Collapsible, Tabs, ScrollArea
references/components-indicators.md - Toolbar, Separator, Progress, Meter, Avatar
references/styling.md - Complete styling guide (Tailwind, CSS Modules, CSS-in-JS)
references/animation.md - Animation patterns (CSS transitions, CSS animations, Motion/JS)
references/composition.md - Composition, customization, and event handling
references/forms-typescript.md - Form integration and TypeScript type patterns
references/utilities.md - CSPProvider, DirectionProvider, mergeProps, useRender
references/accessibility.md - Accessibility features, keyboard navigation, focus management, ARIA
1---2name: base-ui-guide3description: Guide for Base UI (@base-ui/react), an unstyled React component library for building accessible UIs. Use when user asks to "build a component with Base UI", "create a form with Base UI", "style Base UI components", "animate Base UI popover", "use Base UI dialog", "add Base UI select", "implement Base UI tabs", or asks about Base UI accessibility, composition, customization, styling, animation, TypeScript types, or any of its 35+ components. Covers all components (Dialog, Menu, Popover, Select, Combobox, Tabs, Accordion, Toast, Form, Field, Slider, etc.), styling patterns, animations, composition via render props, event customization, form integration, and utilities. Do NOT use for Radix UI (radix-ui), Material UI (MUI @mui/material), or Shadcn/ui - those are separate libraries with different APIs.4---56# Base UI Guide78Base UI (`@base-ui/react`) is an unstyled React component library for building accessible user interfaces. From the creators of Radix, Material UI, and Floating UI. Components are headless, composable, and WAI-ARIA compliant. Supports React 17+ and all modern browsers (Baseline Widely Available). Tree-shakable single package.910**Do NOT use this guide** for Radix UI (radix-ui), Material UI (MUI @mui/material), or Shadcn/ui — those are separate libraries with different APIs.1112## Quick Start1314```bash15npm i @base-ui/react16```1718### Setup19201. **Portals** - Add stacking context isolation to prevent z-index conflicts:2122```css23.root { isolation: isolate; }24```2526```tsx27<body><div className="root">{children}</div></body>28```29302. **iOS 26+ Safari** - For dialog backdrops:3132```css33body { position: relative; }34```3536## Import Pattern3738All components use namespaced compound pattern from a single package:3940```tsx41import { Popover } from '@base-ui/react/popover';4243<Popover.Root>44 <Popover.Trigger>Open</Popover.Trigger>45 <Popover.Portal>46 <Popover.Positioner sideOffset={8}>47 <Popover.Popup>48 <Popover.Arrow />49 <Popover.Title>Title</Popover.Title>50 <Popover.Description>Content</Popover.Description>51 </Popover.Popup>52 </Popover.Positioner>53 </Popover.Portal>54</Popover.Root>55```5657## Core Patterns5859### Styling (components are completely unstyled)6061**CSS Classes** - static or state-dependent:62```tsx63<Switch.Thumb className="SwitchThumb" />64<Switch.Thumb className={(state) => state.checked ? 'checked' : 'unchecked'} />65```6667**Data Attributes** - all components expose state via `data-*` attributes:68```css69.SwitchThumb[data-checked] { background: blue; }70.Popup[data-starting-style] { opacity: 0; transform: scale(0.9); }71```7273**CSS Custom Properties** - dynamic values for layout/animation:74```css75.Indicator { width: var(--slider-indicator-width); }76.Popup { transform-origin: var(--transform-origin); }77```7879Works with Tailwind CSS, CSS Modules, CSS-in-JS, or plain CSS.8081### Composition (render prop)8283Replace default elements with custom components or different HTML tags:8485```tsx86// Custom component (must forward ref and spread props)87<Dialog.Trigger render={<MyButton size="md" />} />8889// Different HTML element90<Menu.Item render={<a href="/profile" />}>Profile</Menu.Item>9192// Render function with state access93<Checkbox.Root render={(props, state) => (94 <span {...props}>{state.checked ? <CheckIcon /> : <BoxIcon />}</span>95)} />96```9798### Server Components (Next.js / RSC)99100All interactive Base UI components require `'use client'` in React Server Component environments. Only static display components (Separator, Avatar without interaction) can be used in server components.101102### Combobox List Render Pattern103104Combobox and Autocomplete use a unique render-children pattern on `List` — pass a function that receives each filtered item:105106```tsx107<Combobox.List>108 {(item) => (109 <Combobox.Item key={item.value} value={item}>110 {item.label}111 </Combobox.Item>112 )}113</Combobox.List>114```115116This differs from Select, where you explicitly `.map()` over items inside `Select.List`.117118### Controlled vs Uncontrolled119120All interactive components support both modes:121122```tsx123// Uncontrolled (internal state)124<Dialog.Root defaultOpen={false}>125126// Controlled (external state)127<Dialog.Root open={isOpen} onOpenChange={setIsOpen}>128```129130### Event Customization131132Change handlers receive `(value, eventDetails)`:133134```tsx135<Dialog.Root onOpenChange={(open, details) => {136 if (details.reason === 'escape-key') {137 details.cancel(); // Prevent closing138 }139}}>140```141142Key `eventDetails` methods: `cancel()`, `allowPropagation()`. Access `reason` for why the change occurred.143144### Animation145146**CSS Transitions** (recommended - can be cancelled midway):147```css148.Popup {149 transition: transform 150ms, opacity 150ms;150 transform-origin: var(--transform-origin);151}152.Popup[data-starting-style],153.Popup[data-ending-style] {154 opacity: 0;155 transform: scale(0.9);156}157```158159**CSS Animations**: Use `[data-open]` / `[data-closed]` with `@keyframes`.160161**JavaScript (Motion)**: Use `keepMounted` + `render` prop + `<AnimatePresence>`.162163### TypeScript164165Types organized by namespace:166```tsx167Tooltip.Root.Props // Component props168Popover.Positioner.State // Internal state type169Combobox.Root.ChangeEventDetails // Event details type170```171172## Component Catalog173174### Overlay & Navigation175| Component | Parts | Description |176|-----------|-------|-------------|177| **Dialog** | Root, Trigger, Portal, Backdrop, Popup, Title, Description, Close | Modal dialog with focus trap |178| **AlertDialog** | Root, Trigger, Portal, Backdrop, Popup, Title, Description, Close | Confirmation dialog (no pointer dismiss) |179| **Popover** | Root, Trigger, Portal, Positioner, Popup, Arrow, Title, Description | Non-modal floating content |180| **Tooltip** | Provider, Root, Trigger, Portal, Positioner, Popup, Arrow | Hover/focus info popup |181| **PreviewCard** | Root, Trigger, Portal, Positioner, Popup, Arrow | Link hover preview |182| **Toast** | Provider, Portal, Viewport, Root, Title, Description, Action, Close | Notification toasts (stacked or anchored) |183| **Menu** | Root, Trigger, Portal, Positioner, Popup, Arrow, Item, Group, Separator + Radio/Checkbox items | Dropdown menu with submenus |184| **ContextMenu** | Root, Trigger, Portal, Positioner, Popup, Item, Group + submenus | Right-click context menu |185| **NavigationMenu** | Root, List, Item, Trigger, Content, Portal, Positioner, Popup, Link | Site navigation with panels |186| **Menubar** | Wrapper + Menu.Root instances | Horizontal application menu bar |187188### Form Controls189| Component | Parts | Description |190|-----------|-------|-------------|191| **Form** | Single wrapper | Form with validation and submission |192| **Field** | Root, Label, Control, Description, Error, Validity | Field wrapper with validation |193| **Fieldset** | Root, Legend | Groups related fields |194| **Input** | Single element | Text input with state data attributes |195| **NumberField** | Root, ScrubArea, Group, Decrement, Input, Increment | Numeric input with stepper |196| **Checkbox** | Root, Indicator | Checkbox with indeterminate support |197| **CheckboxGroup** | Root | Manages multiple checkbox state |198| **Radio** | Root, Indicator + RadioGroup | Radio button group |199| **Select** | Root, Trigger, Value, Portal, Positioner, Popup, List, Item, ItemIndicator | Dropdown select |200| **Combobox** | Root, Input, Trigger, Portal, Positioner, Popup, List, Item + chips | Searchable select with filtering |201| **Autocomplete** | Root, Input, Trigger, Portal, Positioner, Popup, List, Item | Text input with suggestions |202| **Switch** | Root, Thumb | Toggle switch |203| **Slider** | Root, Value, Control, Track, Indicator, Thumb | Range slider (single or multi-thumb) |204| **Toggle** | Single element | Pressable toggle button |205| **ToggleGroup** | Wrapper + Toggle children | Exclusive or multi-select toggles |206| **Button** | Single element | Accessible button |207208### Display & Layout209| Component | Parts | Description |210|-----------|-------|-------------|211| **Accordion** | Root, Item, Header, Trigger, Panel | Expandable content sections |212| **Collapsible** | Root, Trigger, Panel | Single expand/collapse |213| **Tabs** | Root, List, Tab, Indicator, Panel | Tabbed interface |214| **ScrollArea** | Root, Viewport, Content, Scrollbar, Thumb, Corner | Custom scrollbars |215| **Toolbar** | Root, Button, Link, Separator, Group, Input | Action toolbar |216| **Separator** | Single element | Visual divider |217| **Progress** | Root, Track, Indicator, Value, Label | Progress bar |218| **Meter** | Root, Track, Indicator, Value, Label | Gauge/meter display |219| **Avatar** | Root, Image, Fallback | Profile image with fallback |220221### Utilities222| Utility | Purpose |223|---------|---------|224| **CSPProvider** | Apply nonce to inline styles/scripts for CSP |225| **DirectionProvider** | Enable RTL behavior for components |226| **mergeProps** | Merge React props with special handler/class/style merging |227| **useRender** | Hook to enable render prop pattern in custom components |228229## Key Rules2302311. **Always use `isolation: isolate`** on app root for portal z-index stacking2322. **Components are unstyled** - you must provide all CSS2333. **Custom components in `render` must forward ref and spread props**2344. **Use data attributes for state-based styling**, not className toggling2355. **CSS transitions > CSS animations** for interruptible open/close effects2366. **Animate opacity** (even 0.9999) so Base UI detects animation completion before unmounting2377. **Form fields need `name` prop** on Field.Root for form submission2388. **Field.Label uses `nativeLabel` prop** - set `false` for button-based controls (Select, Combobox)2399. **Popup components** follow: Root > Trigger > Portal > Positioner > Popup > Arrow pattern24010. **`preventBaseUIHandler()`** on React events to bypass Base UI's internal event handling241242## Common Pitfalls243244- **Portal z-index issues**: Forgot `isolation: isolate` on app root - popups appear behind content245- **Animation not completing**: Not animating `opacity` - Base UI uses `element.getAnimations()` to detect completion; animate opacity even to `0.9999` if not otherwise needed246- **Select/Combobox label not associating**: Need `nativeLabel={false}` on `Field.Label` for button-based controls (Select, Combobox)247- **Popup appearing behind content**: Missing `Portal` wrapper or stacking context not set up248- **Form values not collected on submit**: Missing `name` prop on `Field.Root`249- **Nested popups all close on Esc**: Default behavior stops propagation; use `eventDetails.allowPropagation()` if you want parent popups to also close250- **Motion exit animations not playing**: Must use `keepMounted` on Portal + controlled `open` state + `<AnimatePresence>` for unmounted components251252## Common CSS Variables253254Popup/floating components expose:255- `--anchor-width`, `--anchor-height` - Trigger element dimensions256- `--available-width`, `--available-height` - Available space257- `--transform-origin` - Animation origin point258259Sizing components expose:260- `--accordion-panel-height`, `--collapsible-panel-height` - Panel dimensions261- `--slider-*`, `--scroll-area-*` - Component-specific sizing262- `--active-tab-left`, `--active-tab-width` - Tab indicator positioning263264## Reference Files265266- `references/components-dialogs.md` - Dialog, AlertDialog, Popover, Tooltip, PreviewCard267- `references/components-menus.md` - Toast, Menu, ContextMenu, NavigationMenu, Menubar, shared patterns268- `references/components-form-fields.md` - Form, Field, Fieldset, Input, NumberField, Checkbox, CheckboxGroup, Radio269- `references/components-form-controls.md` - Select, Combobox, Autocomplete, Switch, Slider, Toggle, ToggleGroup, Button270- `references/components-panels.md` - Accordion, Collapsible, Tabs, ScrollArea271- `references/components-indicators.md` - Toolbar, Separator, Progress, Meter, Avatar272- `references/styling.md` - Complete styling guide (Tailwind, CSS Modules, CSS-in-JS)273- `references/animation.md` - Animation patterns (CSS transitions, CSS animations, Motion/JS)274- `references/composition.md` - Composition, customization, and event handling275- `references/forms-typescript.md` - Form integration and TypeScript type patterns276- `references/utilities.md` - CSPProvider, DirectionProvider, mergeProps, useRender277- `references/accessibility.md` - Accessibility features, keyboard navigation, focus management, ARIA