Stable in React
Menu
A list of actions in a dropdown, opened by a button and navigated with the keyboard.
Install#
One package per framework. Menu's parts come from it; the anatomy tab at the top shows how they nest.
bun add @▢▢▢▢/react25 parts. The example uses 9 of them; the data does not say which are required.
Menu.RootGroups all parts of the menu.Menu.TriggerA button that opens the menu.Menu.PortalA portal element that moves the popup to a different part of the DOM.Menu.PositionerPositions the menu popup against the trigger.Menu.PopupA container for the menu items.Menu.ItemAn individual interactive item in the menu.Menu.CheckboxItemA menu item that toggles a setting on or off.Menu.SubmenuRootGroups all parts of a submenu.Menu.SubmenuTriggerA menu item that opens a submenu.Menu.ArrowDisplays an element positioned against the menu anchor. Not in the example.Menu.BackdropAn overlay displayed beneath the menu popup. Not in the example.Menu.CheckboxItemIndicatorIndicates whether the checkbox item is ticked. Not in the example.Menu.ClearA button that clears the input text. Not in the example.Menu.EmptyA message shown when the menu has no matching items. Not in the example.Menu.FilterProviderEnables filtering for the menu or submenu it wraps. Not in the example.Menu.GroupGroups related menu items with the corresponding label. Not in the example.Menu.GroupLabelAn accessible label that is automatically associated with its parent group. Not in the example.Menu.InputA search field that filters the menu items. Not in the example.Menu.LinkItemA link in the menu that can be used to navigate to a different page or section. Not in the example.Menu.ListGroups menu items so other content, such as a filter input, can share the popup. Not in the example.Menu.RadioGroupGroups related radio items. Not in the example.Menu.RadioItemA menu item that works like a radio button in a given group. Not in the example.Menu.RadioItemIndicatorIndicates whether the radio item is selected. Not in the example.Menu.SeparatorA separator element accessible to screen readers. Not in the example.Menu.ViewportA viewport for displaying content transitions. Not in the example.
Examples#
Common ways to put it to work. Each one runs live.
openOnHover and delay open the menu when the pointer rests on the trigger.
MenuOpenOnHover.tsxStyling and accessibility#
The parts ship no styles. Style their states with these attributes; the CSS tab at the top has a sheet. The same CSS works in all five frameworks.
[data-popup-open]Present when the corresponding menu is open. On Trigger, SubmenuTrigger.[data-pressed]Present when the trigger is pressed. On Trigger.[data-disabled]Present when the trigger is disabled. On Trigger, Item, CheckboxItem, SubmenuTrigger, CheckboxItemIndicator, Clear, RadioItem, RadioItemIndicator.[data-open]Present when the menu popup is open. On Positioner, Popup, Arrow, Backdrop.[data-closed]Present when the menu popup is closed. On Positioner, Popup, Arrow, Backdrop.[data-anchor-hidden]Present when the anchor is hidden. On Positioner.[data-side]Indicates which side the popup is positioned relative to the anchor. On Positioner, Popup, Arrow.[data-align]Indicates how the popup is aligned relative to the specified side. On Positioner, Popup, Arrow.--available-widthThe available width between the anchor and the edge of the viewport. On Positioner.--available-heightThe available height between the anchor and the edge of the viewport. On Positioner.--anchor-widthThe anchor's width. On Positioner.--anchor-heightThe anchor's height. On Positioner.--transform-originThe coordinates that this element is anchored to. Used for animations and transitions. On Positioner.--positioner-widthThe width of the menu's positioner. It is important to setwidthto this value when using CSS to animate size changes. On Positioner.--positioner-heightThe height of the menu's positioner. It is important to setheightto this value when using CSS to animate size changes. On Positioner.[data-starting-style]Present when the menu begins animating in. On Popup, Backdrop, CheckboxItemIndicator, RadioItemIndicator.[data-ending-style]Present when the menu is animating out. On Popup, Backdrop, CheckboxItemIndicator, RadioItemIndicator.[data-instant]Present if animations should be instant. On Popup, Viewport.[data-highlighted]Present when the menu item is highlighted. On Item, CheckboxItem, SubmenuTrigger, Input, LinkItem, RadioItem.[data-checked]Present when the menu checkbox item is checked. On CheckboxItem, CheckboxItemIndicator, RadioItem, RadioItemIndicator.[data-unchecked]Present when the menu checkbox item is not checked. On CheckboxItem, CheckboxItemIndicator, RadioItem, RadioItemIndicator.[data-uncentered]Present when the menu arrow is uncentered. On Arrow.[data-orientation]Indicates the orientation of the separator. On Separator.[data-current]Applied to the direct child of the viewport when no transitions are present or the new content when it's entering. On Viewport.[data-previous]Applied to the direct child of the viewport that contains the exiting content when transitions are present. On Viewport.[data-activation-direction]Indicates the direction from which the popup was activated. This can be used to create directional animations based on how the popup was triggered. Contains space-separated values for both horizontal and vertical axes. On Viewport.[data-transitioning]Indicates that the viewport is currently transitioning between old and new content. On Viewport.--popup-widthThe width of the parent popup. This variable is placed on the 'previous' container and stores the width of the popup when the previous content was rendered. It can be used to freeze the dimensions of the popup when animating between different content. On Viewport.--popup-heightThe height of the parent popup. This variable is placed on the 'previous' container and stores the height of the popup when the previous content was rendered. It can be used to freeze the dimensions of the popup when animating between different content. On Viewport.
Keyboard
- EnterSpaceArrowDownArrowUpOpens the menu On Trigger.
- ArrowDownOpens the menu and focuses the first item On Trigger.
- ArrowUpOpens the menu and focuses the last item On Trigger.
- ArrowDownArrowUpMoves to the next or previous item On Popup.
- HomeEndMoves to the first or last item On Popup.
- Moves to the next item whose text, or
label, starts with what was typed On Item. - EnterActivates the highlighted item and closes the menu On Item.
- SpaceChecks or unchecks a checkbox item On CheckboxItem.
- EnterChecks or unchecks a checkbox item On CheckboxItem.
- EnterSpaceSelects a radio item On RadioItem.
- ArrowRightOpens a submenu and focuses its first item (
ArrowLeftin right-to-left) On SubmenuTrigger. - ArrowLeftCloses a submenu and returns focus to its trigger On SubmenuTrigger.
- EscapeCloses the menu and keeps focus on the trigger On Popup.
- EscapeIn a submenu, closes only the submenu unless
closeParentOnEscis on On SubmenuRoot. - TabCloses the menu and moves focus to the element after the trigger On Popup.
Set for you
a screen reader says the button opens a menu and whether it is openTriggeraria-haspopup="menu",aria-expanded,aria-controlsthe popup is announced as a menuPopuprole="menu"each action is read as a menu itemItemrole="menuitem"a setting is read with its on or off stateCheckboxItemrole="menuitemcheckbox",aria-checkedthe chosen option of a set is readRadioItemrole="menuitemradio",aria-checkedrelated items are read under their labelGrouprole="group",aria-labelledbyto its GroupLabela screen reader knows the item opens another menuSubmenuTriggeraria-controlsto the submenugroups are divided for screen readers tooSeparatorrole="separator"the tick is decoration; the state is on the itemCheckboxItemIndicatoraria-hidden="true"the decorative arrow is not readArrowaria-hidden="true"
API reference#
99 props across 25 parts, in React syntax, and className, style, render once for every part. Open a row to try it.
Menu · all partsclassNameCSS class applied to the element, or a function that
returns a class based on the component's state.string | ((state: State) => string | undefined)styleStyle applied to the element, or a function that
returns a style object based on the component's state.React.CSSProperties | ((state: State) => React.CSSProperties | undefined)renderAllows you to replace the component's HTML element
with a different tag, or compose it with another component.React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | ComponentRenderFn<HTMLProps, State>Use it in React#
What differs from the React API. Switch the framework at the top of the page.
@▢▢▢▢/react is the React 19 package. Its parts, props, data attributes and error messages are upstream Base UI's, and upstream's own tests run against it.
- Parts
Each component is its own entry point and exports one namespace named after it.
import { Switch } from '@base-ui-next/react/switch' export function Example() { return ( <Switch.Root> <Switch.Thumb /> </Switch.Root> ) }A part renders the element its API reference names, such as a
<span>forSwitch.Root. - Props and events
Props and callbacks have upstream's names and signatures:
onCheckedChange(checked, details),onOpenChange(open, details),onValueChange(value, details).detailscarriesreason,event,cancel()andallowPropagation(). Native handlers are React's (onClick,onKeyDown), andevent.preventBaseUIHandler()stops a part's own handler. - Styling
classNametakes a string or a function(state) => string;styletakes an object or a function(state) => object. The state'sdata-*attributes are on the element for CSS. renderrendertakes an element (render={<a href="/docs" />}) or a function(props, state) => elementthat spreadspropson what it returns.- Refs
refreaches the part's element. Imperative handles are ref props, as upstream:inputRef, andactionsRef({ validate }on Field and Form,{ unmount, close }on Dialog). - Binding
A part is controlled when its value prop (
checked,open,value) is set, and uncontrolled with thedefaultform (defaultChecked,defaultOpen,defaultValue). React has no two-way binding: pair the value with its change callback. - From @base-ui/reactChange the import from
@base-ui/react/<component>to@▢▢▢▢/react/<component>. - From @base-ui/reactNothing else changes: props, parts, data attributes and errors are the same.