Knowledge base from the Base UI (base-ui.com, @base-ui/react) documentation — unstyled, accessible React component library from the creators of Radix, Material UI, and Floating UI. Use when building with Base UI directly, looking up a component's anatomy/props/data-attributes, choosing between similar components (Dialog vs AlertDialog vs Drawer, Autocomplete vs Combobox vs Select), or implementing composition/styling/animation patterns like the render prop, data-state styling, or collision-aware positioning. Also relevant when working in shadcn/ui, since shadcn/ui is now built on Base UI.
Package: @base-ui/react | Components: 45 | Guides: 6 | Utilities: 4 | Generated: 2026-08-25
Dialog, Select, Forms-style topics; I find and read the matching chapterch021; I load that specific chapterWhen you ask about a topic not covered in Core Patterns below, I will read the relevant chapter file before answering.
Anatomy first. Every component is Root + named sub-parts (Trigger, Popup, Item...) — always start from a component's Anatomy before reaching for individual props.
render is the universal composition prop — not asChild. Nearly every part accepts render={<Element/>} (swap the rendered element) or render={(props, state) => <el/>} (function form, full control + state access). The target must spread props and forward its ref. Coming from Radix Primitives: render replaces asChild conceptually, but the syntax differs.
Style off data-*, never off tracked JS state. Stateful parts expose data-* attributes (data-open/data-closed, data-checked, data-highlighted, data-disabled, ...) — target these directly in CSS/CSS-in-JS. className/style also accept a (state) => value function form for anything not already exposed as a data attribute.
Unstyled by design. Nothing renders visually except structure and behavior — plan both functional (positioning/sizing) and presentational styles from the start.
Positioned overlays share one API. Menu, Popover, Select, Combobox, Autocomplete, Tooltip, ContextMenu, NavigationMenu, PreviewCard, and Toast all expose the same side/align/collisionBoundary/sticky family on Positioner, and the same --anchor-width/-height, --available-width/-height, --transform-origin CSS variables. Learn it once on any of them — except Select's alignItemWithTrigger mode, which overrides side/align while active.
CSS transitions animate [data-starting-style]/[data-ending-style]; JS animation needs keepMounted. CSS transitions/keyframes work out of the box keyed off data-* state. A JS library (Motion) needs Portal keepMounted + AnimatePresence, or a state.open-driven render function for always-mounted components — and must animate opacity (even minimally) so Base UI's getAnimations() completion check fires.
Detached triggers use Handle. Component.createHandle() + the handle prop connects a Trigger to a Root that isn't its sibling (Dialog, AlertDialog, Popover, Menu, Tooltip, PreviewCard, Drawer) — call handle.open()/.close() only from event handlers/effects.
Form controls share one field-state vocabulary. data-valid/data-invalid, data-dirty, data-touched, data-filled, data-focused recur on nearly every form-capable component; Field.Root name="..." + Fieldset.Root render={<Group/>} is the accessible naming/validation/grouping backbone (ch009, ch023, ch024).
Roving tabindex is built in. Menu items, radio items, tabs, toggle groups, toolbar items share one Tab stop with internal arrow-key movement — configure loopFocus/orientation, don't hand-roll it.
Accessibility is opinionated, not optional. ARIA roles, keyboard interaction, and focus management (initialFocus/finalFocus) are handled internally — visual focus styling, color contrast, and accessible labelling (aria-label, Field.Label) are still your responsibility.
| # | Title | Key Concepts |
|---|---|---|
| ch001 | Introduction | headless, render prop origin, shadcn/ui foundation |
| ch002 | Getting Started | install, portal stacking, iOS Safari fix |
| ch003 | Accessibility | keyboard nav, focus management, contrast |
| ch004 | Releases & Versioning | 1.0.0 milestone, canary installs |
| # | Title | Key Concepts |
|---|---|---|
| ch005 | Styling | className/style function form, data attributes, CSS variables |
| ch006 | Animation | CSS transitions/keyframes, Motion integration patterns |
| ch007 | Composition | render prop, nesting, function form |
| ch008 | Customization | eventDetails, cancel/allowPropagation, controlled state |
| ch009 | Forms | naming, constraint/custom/server validation, RHF/TanStack |
| ch010 | TypeScript | Props/State/ChangeEventDetails namespaces |
| # | Title | Key Concepts |
|---|---|---|
| ch011 | Accordion | multiple, panel height CSS var |
| ch012 | Alert Dialog | Handle, nested dialogs, initialFocus |
| ch013 | Autocomplete | free-form text, filtering, grid mode |
| ch014 | Avatar | Image/Fallback, delay |
| ch015 | Button | nativeButton, never for links |
| ch016 | Checkbox | tri-state, indeterminate, labeling patterns |
| ch017 | Checkbox Group | parent checkbox, allValues |
| ch018 | Collapsible | single-panel open/close |
| ch019 | Combobox | filterable Select, chips, multi-select |
| ch020 | Context Menu | right-click, must be an enhancement |
| ch021 | Dialog | modal, Handle, no gesture support |
| ch022 | Drawer | swipe, snap points, indent effect |
| ch023 | Field | Label/Control/Error, shared state attributes |
| ch024 | Fieldset | group labeling via render composition |
| ch025 | Form | errors, onFormSubmit, validationMode |
| ch026 | Input | plain text control |
| ch027 | Menu | items, submenus, Viewport transitions |
| ch028 | Menubar | cross-menu arrow navigation |
| ch029 | Meter | static read-only gauge |
| ch030 | Navigation Menu | shared Viewport, site nav |
| ch031 | Number Field | scrubbing, stepping, locale formatting |
| ch032 | OTP Field | autoSubmit, mask, autoComplete |
| ch033 | Popover | non-modal default, hover trigger |
| ch034 | Preview Card | hover-only, sighted-mouse-only |
| ch035 | Progress | indeterminate, complete, progressing |
| ch036 | Radio | mutually exclusive, RadioGroup |
| ch037 | Scroll Area | native scroll, overlay scrollbar |
| ch038 | Select | alignItemWithTrigger, no filtering |
| ch039 | Separator | orientation |
| ch040 | Slider | multi-thumb, minStepsBetweenValues |
| ch041 | Switch | two-state, no indeterminate |
| ch042 | Tabs | Indicator, activateOnFocus, keepMounted |
| ch043 | Toast | imperative manager, stacking CSS vars |
| ch044 | Toggle | single pressed/unpressed button |
| ch045 | Toggle Group | multiple vs. exclusive |
| ch046 | Toolbar | mixed controls, one input max |
| ch047 | Tooltip | sighted-only, disabled on touch |
| # | Title | Key Concepts |
|---|---|---|
| ch048 | CSP Provider | nonce, disableStyleElements |
| ch049 | Direction Provider | RTL behavior, useDirection |
| ch050 | mergeProps | className/style/handler merging |
| ch051 | useRender | building your own render-accepting component |
render / composition → ch001, ch007, ch051Handle) → ch012, ch021, ch027, ch033, ch034This skill covers the Base UI (@base-ui/react) documentation as of the fetch date in the source (2026-08-23) — component anatomy, props/data-attributes/CSS variables, and the Handbook guides (styling, animation, composition, customization, forms, TypeScript). The 30+ dated changelog entries in the source are not reproduced 1:1 — ch004 summarizes the versioning approach and cites only notable milestones.
Relationship to radix-primitives-docs. Both skills cover unstyled, accessible React primitive libraries — Base UI (from the team behind Radix, Material UI, and Floating UI) and Radix Primitives (WorkOS) are competing primitive layers, not one built on the other. As of this documentation, shadcn/ui is built on Base UI, not Radix — a shift from shadcn/ui's earlier Radix-based versions. If working in a shadcn/ui codebase, check which underlying primitive library the installed version actually uses before consulting either skill. Base UI additionally ships several components Radix Primitives doesn't have in this project's indexed set: Autocomplete, Combobox, Toast, Meter, NumberField, OTPField, PreviewCard, Drawer, CSPProvider. The core API difference to remember when moving between them: Base UI's composition prop is render (element or function form); Radix's is asChild (always paired with a literal child element).