Menu
Accessible dropdown Menu
component that follows the WAI-ARIA Menu or Menu bar Pattern. It also includes a MenuButton
component that follows the WAI-ARIA Menu Button Pattern.
#Installation
npm install reakit
Learn more in Get started.
#Usage
import { useMenuState, Menu, MenuItem, MenuButton, MenuSeparator, } from "reakit/Menu"; function Example() { const menu = useMenuState(); return ( <> <MenuButton {...menu}>Preferences</MenuButton> <Menu {...menu} aria-label="Preferences"> <MenuItem {...menu}>Settings</MenuItem> <MenuItem {...menu} disabled> Extensions </MenuItem> <MenuSeparator {...menu} /> <MenuItem {...menu}>Keyboard shortcuts</MenuItem> </Menu> </> ); }
#Menu actions
You can use either onClick
or href
props on MenuItem
to define menu actions.
import { useMenuState, Menu, MenuItem, MenuButton, MenuSeparator, } from "reakit/Menu"; function Example() { const menu = useMenuState(); return ( <> <MenuButton {...menu}>Menu</MenuButton> <Menu {...menu} aria-label="Example"> <MenuItem {...menu} onClick={() => { menu.hide(); console.log("clicked on button"); }} > Button </MenuItem> <MenuItem {...menu} as="a" href="#" onClick={menu.hide}> Link </MenuItem> </Menu> </> ); }
#Initial focus
When opening Menu
, focus is usually set on the first MenuItem
. You can set the initial focus to be the menu container itself by just passing tabIndex={0}
to it. This will be ignored if the menu is opened by using arrow keys.
import { useMenuState, Menu, MenuItem, MenuButton } from "reakit/Menu"; function Example() { const menu = useMenuState(); return ( <> <MenuButton {...menu}>Preferences</MenuButton> <Menu {...menu} tabIndex={0} aria-label="Preferences"> <MenuItem {...menu}>Settings</MenuItem> <MenuItem {...menu}>Extensions</MenuItem> <MenuItem {...menu}>Keyboard shortcuts</MenuItem> </Menu> </> ); }
Alternatively, you can define another element to get the initial focus with React hooks:
import React from "react"; import { Button } from "reakit/Button"; import { useMenuState, Menu, MenuItem, MenuButton } from "reakit/Menu"; function Example() { const menu = useMenuState(); const ref = React.useRef(); React.useEffect(() => { if (menu.visible) { ref.current.focus(); } }, [menu.visible]); return ( <> <MenuButton {...menu}>Preferences</MenuButton> <Menu {...menu} aria-label="Preferences"> <MenuItem {...menu}>Settings</MenuItem> <MenuItem {...menu} ref={ref}> Extensions </MenuItem> <MenuItem {...menu}>Keyboard shortcuts</MenuItem> </Menu> </> ); }
#Submenu
Menu
can be used independently or nested within another one.
import React from "react"; import { useMenuState, Menu, MenuItem, MenuButton, MenuSeparator, } from "reakit/Menu"; const PreferencesMenu = React.forwardRef((props, ref) => { const menu = useMenuState(); return ( <> <MenuButton ref={ref} {...menu} {...props}> Preferences </MenuButton> <Menu {...menu} aria-label="Preferences"> <MenuItem {...menu}>Settings</MenuItem> <MenuItem {...menu} disabled> Extensions </MenuItem> <MenuSeparator {...menu} /> <MenuItem {...menu}>Keyboard shortcuts</MenuItem> </Menu> </> ); }); function Example() { const menu = useMenuState(); return ( <> <MenuButton {...menu}>Code</MenuButton> <Menu {...menu} aria-label="Code"> <MenuItem {...menu}>About Visual Studio Code</MenuItem> <MenuItem {...menu}>Check for Updates...</MenuItem> <MenuSeparator {...menu} /> <MenuItem {...menu} as={PreferencesMenu} /> </Menu> </> ); }
#Menu with dialog
Reakit is built with composition in mind! You can compose any other component with Menu
. You can nest Dialogs inside it by using the same approach described on Submenu.
import React from "react"; import { Button } from "reakit/Button"; import { useDialogState, Dialog, DialogDisclosure, DialogBackdrop, } from "reakit/Dialog"; import { useMenuState, Menu, MenuItem, MenuButton, MenuSeparator, } from "reakit/Menu"; const UpdatesDialog = React.forwardRef((props, ref) => { const dialog = useDialogState(); return ( <> <DialogDisclosure ref={ref} {...dialog} {...props}> Check for Updates... </DialogDisclosure> <Dialog {...dialog} aria-label="Check for Updates"> <p>There are currently no updates available.</p> <Button onClick={dialog.hide}>OK</Button> </Dialog> </> ); }); function Example() { const menu = useMenuState(); return ( <> <MenuButton {...menu}>Code</MenuButton> <Menu {...menu} aria-label="Code"> <MenuItem {...menu}>About Visual Studio Code</MenuItem> <MenuItem {...menu} as={UpdatesDialog} /> <MenuSeparator {...menu} /> <MenuItem {...menu}>Preferences</MenuItem> </Menu> </> ); }
#Menu bar
You can combine multiple Menu
s to compose a MenuBar
by using the same approach described on Submenu. Each Menu
can be used separately or in combination with others.
import React from "react"; import { useMenuState, useMenuBarState, Menu, MenuButton, MenuItem, MenuSeparator, MenuBar, MenuGroup, MenuItemCheckbox, MenuItemRadio, } from "reakit/Menu"; // OPEN RECENT const OpenRecentMenu = React.forwardRef((props, ref) => { const menu = useMenuState(); return ( <> <MenuButton ref={ref} {...menu} {...props}> Open Recent </MenuButton> <Menu {...menu} aria-label="Open Recent"> <MenuItem {...menu}>Reopen Closed Editor</MenuItem> <MenuSeparator {...menu} /> <MenuItem {...menu}>More...</MenuItem> <MenuSeparator {...menu} /> <MenuItem {...menu}>Clear Recently Opened</MenuItem> </Menu> </> ); }); // FILE const FileMenu = React.forwardRef((props, ref) => { const menu = useMenuState(); return ( <> <MenuButton ref={ref} {...menu} {...props}> File </MenuButton> <Menu {...menu} aria-label="File"> <MenuItem {...menu}>New File</MenuItem> <MenuItem {...menu}>New Window</MenuItem> <MenuSeparator {...menu} /> <MenuItem {...menu}>Open...</MenuItem> <MenuItem {...menu}>Open Workspace...</MenuItem> <MenuItem {...menu} as={OpenRecentMenu} /> </Menu> </> ); }); // EDIT const EditMenu = React.forwardRef((props, ref) => { const menu = useMenuState(); return ( <> <MenuButton ref={ref} {...menu} {...props}> Edit </MenuButton> <Menu {...menu} aria-label="Edit"> <MenuItem {...menu}>Undo</MenuItem> <MenuItem {...menu}>Redo</MenuItem> <MenuSeparator {...menu} /> <MenuItem {...menu}>Cut</MenuItem> <MenuItem {...menu}>Copy</MenuItem> <MenuItem {...menu}>Paste</MenuItem> </Menu> </> ); }); // VIEW const ViewMenu = React.forwardRef((props, ref) => { const menu = useMenuState(); return ( <> <MenuButton ref={ref} {...menu} {...props}> View </MenuButton> <Menu {...menu} aria-label="View"> <MenuGroup {...menu}> <MenuItemRadio {...menu} name="windows" value="explorer"> Explorer </MenuItemRadio> <MenuItemRadio {...menu} name="windows" value="search"> Search </MenuItemRadio> <MenuItemRadio {...menu} name="windows" value="debug"> Debug </MenuItemRadio> <MenuItemRadio {...menu} name="windows" value="extensions"> Extensions </MenuItemRadio> </MenuGroup> <MenuSeparator {...menu} /> <MenuItemCheckbox {...menu} name="toggles" value="word-wrap"> Toggle Word Wrap </MenuItemCheckbox> <MenuItemCheckbox {...menu} name="toggles" value="minimap"> Toggle Minimap </MenuItemCheckbox> <MenuItemCheckbox {...menu} name="toggles" value="breadcrumbs"> Toggle Breadcrumbs </MenuItemCheckbox> </Menu> </> ); }); function Example() { const menu = useMenuBarState(); return ( <MenuBar {...menu}> <MenuItem {...menu} as={FileMenu} /> <MenuItem {...menu} as={EditMenu} /> <MenuItem {...menu} as={ViewMenu} /> </MenuBar> ); }
#Animating
Menu
uses Popover underneath, so you can use the same approaches as described in the Animating section there.
import { css } from "emotion"; import { useMenuState, Menu, MenuItem, MenuButton } from "reakit/Menu"; const styles = css` display: flex; flex-direction: column; background: white; transition: opacity 250ms ease-in-out, transform 250ms ease-in-out; opacity: 0; transform-origin: top center; transform: scaleY(0); [data-enter] & { opacity: 1; transform: scaleY(1); } `; function Example() { const menu = useMenuState({ animated: 250 }); return ( <> <MenuButton {...menu}>Preferences</MenuButton> <Menu {...menu} aria-label="Preferences" style={{ border: 0, background: "none", padding: 0 }} > <div className={styles}> <MenuItem {...menu}>Item 1</MenuItem> <MenuItem {...menu}>Item 2</MenuItem> <MenuItem {...menu}>Item 3</MenuItem> </div> </Menu> </> ); }
#Abstracting
You can build your own Menu
component with a different API on top of Reakit.
Be careful not to accidentally shadow props coming in from the menu state.
import React from "react"; import { useMenuState, Menu as BaseMenu, MenuItem, MenuButton, MenuSeparator, } from "reakit/Menu"; const Menu = React.forwardRef( ({ disclosure, menuItems, menuProps, ...props }, ref) => { const menu = useMenuState(); return ( <> <MenuButton ref={ref} {...menu} {...props} {...disclosure.props}> {(disclosureProps) => React.cloneElement(disclosure, disclosureProps)} </MenuButton> <BaseMenu {...menu} {...menuProps}> {menuItems.map((item, i) => { if (item.type === MenuSeparator) { return React.cloneElement(item, { ...menu, key: item.key || i, ...item.props, }); } return ( <MenuItem {...menu} {...item.props} key={item.key || i}> {(itemProps) => React.cloneElement(item, itemProps)} </MenuItem> ); })} </BaseMenu> </> ); } ); function Example() { return ( <Menu menuProps={{ "aria-label": "Custom menu" }} disclosure={<button>Custom menu</button>} menuItems={[ <button>Custom item 1</button>, <button>Custom item 2</button>, <button>Custom item 3</button>, <MenuSeparator />, <Menu menuProps={{ "aria-label": "Sub Menu" }} disclosure={<button>Sub Menu</button>} menuItems={[ <button>Custom item 4</button>, <button>Custom item 5</button>, ]} />, ]} /> ); }
#Performance
If you notice performance issues when rendering several MenuItem
s, you can do the following:
- Pass an
id
prop to eachMenuItem
. - Memoize all non-primitive props that you're passing to
MenuItem
, including event handlers (e.g.onClick
) and thechildren
prop.
MenuItem
will compare the passed id
with menu.currentId
and, if the other props haven't been changed, it'll only re-render if it's the previous or the current active item.
import React from "react"; import { useMenuState, Menu, MenuButton, MenuItem } from "reakit/Menu"; const items = Array.from({ length: 25 }).map((_, i) => `item-${i}`); function Example() { const menu = useMenuState({ loop: true }); const onClick = React.useCallback((event) => { window.alert(event.currentTarget.id); }, []); // If children aren't primitive values (like strings), memoize them with // React.useCallback const children = React.useCallback( (itemProps) => ( <span {...itemProps}> <span>{itemProps.id}</span> </span> ), [] ); return ( <> <MenuButton {...menu}>Performance</MenuButton> <Menu {...menu} aria-label="Performance"> {items.map((id) => ( <MenuItem {...menu} key={id} id={id} onClick={onClick}> {children} </MenuItem> ))} </Menu> </> ); }
#Accessibility
Menu
has rolemenu
.MenuBar
has rolemenubar
.Menu
andMenuBar
extend the accessibility features of Composite.MenuButton
extends the accessibility features of PopoverDisclosure, which means it setsaria-haspopup
andaria-expanded
attributes accordingly.MenuItem
has rolemenuitem
.MenuItem
extends the accessibility features of CompositeItem, which means it uses the roving tabindex method to manage focus.MenuItemCheckbox
has rolemenuitemcheckbox
.MenuItemRadio
has rolemenuitemradio
.- Pressing Enter on
MenuButton
opens its menu (or submenu) and places focus on its first item. - Pressing Space on
MenuItemCheckbox
changes the state without closingMenu
. - Pressing Space on a
MenuItemRadio
that is not checked, without closingMenu
, checks the focusedMenuItemRadio
and unchecks any other checkedMenuItemRadio
in the same group. - Pressing any key that corresponds to a printable character moves focus to the next
MenuItem
in the currentMenu
orMenuBar
whose label begins with that printable character.
Learn more in Accessibility.
#Composition
Menu
usesMenuBar
and Popover.MenuArrow
uses PopoverArrow.MenuButton
uses PopoverDisclosure.MenuGroup
uses Role.MenuItem
uses CompositeItem.MenuItemCheckbox
usesMenuItem
and Checkbox.MenuItemRadio
usesMenuItem
and Radio.MenuSeparator
uses Separator.MenuBar
uses Composite.
Learn more in Composition.
#Props
#useMenuBarState
-
baseId
string
ID that will serve as a base for all the items IDs.
-
unstable_virtual
boolean
If enabled, the composite element will act as an aria-activedescendant container instead of roving tabindex. DOM focus will remain on the composite while its items receive virtual focus.
-
rtl
boolean
Determines how
next
andprevious
functions will behave. Ifrtl
is set totrue
, they will be inverted. This only affects the composite widget behavior. You still need to setdir="rtl"
on HTML/CSS. -
orientation
"horizontal" | "vertical" | undefined
Defines the orientation of the composite widget. If the composite has a single row or column (one-dimensional), the
orientation
value determines which arrow keys can be used to move focus:undefined
: all arrow keys work.horizontal
: only left and right arrow keys work.vertical
: only up and down arrow keys work.
It doesn't have any effect on two-dimensional composites.
-
currentId
string | null | undefined
The current focused item
id
.undefined
will automatically focus the first enabled composite item.null
will focus the base composite element and users will be able to navigate out of it using arrow keys.- If
currentId
is initially set tonull
, the base composite element itself will have focus and users will be able to navigate to it using arrow keys.
-
loop
boolean | "horizontal" | "vertical"
On one-dimensional composites:
true
loops from the last item to the first item and vice-versa.horizontal
loops only iforientation
ishorizontal
or not set.vertical
loops only iforientation
isvertical
or not set.- If
currentId
is initially set tonull
, the composite element will be focused in between the last and first items.
On two-dimensional composites:
true
loops from the last row/column item to the first item in the same row/column and vice-versa. If it's the last item in the last row, it moves to the first item in the first row and vice-versa.horizontal
loops only from the last row item to the first item in the same row.vertical
loops only from the last column item to the first item in the column row.- If
currentId
is initially set tonull
, vertical loop will have no effect as moving down from the last row or up from the first row will focus the composite element. - If
wrap
matches the value ofloop
, it'll wrap between the last item in the last row or column and the first item in the first row or column and vice-versa.
-
wrap
boolean | "horizontal" | "vertical"
Has effect only on two-dimensional composites. If enabled, moving to the next item from the last one in a row or column will focus the first item in the next row or column and vice-versa.
true
wraps between rows and columns.horizontal
wraps only between rows.vertical
wraps only between columns.- If
loop
matches the value ofwrap
, it'll wrap between the last item in the last row or column and the first item in the first row or column and vice-versa.
-
shift
boolean
Has effect only on two-dimensional composites. If enabled, moving up or down when there's no next item or the next item is disabled will shift to the item right before it.
-
unstable_values
{ [x: string]: any; }
Stores the values of radios and checkboxes within the menu.
#useMenuState
-
baseId
string
ID that will serve as a base for all the items IDs.
-
unstable_virtual
boolean
If enabled, the composite element will act as an aria-activedescendant container instead of roving tabindex. DOM focus will remain on the composite while its items receive virtual focus.
-
rtl
boolean
Determines how
next
andprevious
functions will behave. Ifrtl
is set totrue
, they will be inverted. This only affects the composite widget behavior. You still need to setdir="rtl"
on HTML/CSS. -
orientation
"horizontal" | "vertical" | undefined
Defines the orientation of the composite widget. If the composite has a single row or column (one-dimensional), the
orientation
value determines which arrow keys can be used to move focus:undefined
: all arrow keys work.horizontal
: only left and right arrow keys work.vertical
: only up and down arrow keys work.
It doesn't have any effect on two-dimensional composites.
-
currentId
string | null | undefined
The current focused item
id
.undefined
will automatically focus the first enabled composite item.null
will focus the base composite element and users will be able to navigate out of it using arrow keys.- If
currentId
is initially set tonull
, the base composite element itself will have focus and users will be able to navigate to it using arrow keys.
-
loop
boolean | "horizontal" | "vertical"
On one-dimensional composites:
true
loops from the last item to the first item and vice-versa.horizontal
loops only iforientation
ishorizontal
or not set.vertical
loops only iforientation
isvertical
or not set.- If
currentId
is initially set tonull
, the composite element will be focused in between the last and first items.
On two-dimensional composites:
true
loops from the last row/column item to the first item in the same row/column and vice-versa. If it's the last item in the last row, it moves to the first item in the first row and vice-versa.horizontal
loops only from the last row item to the first item in the same row.vertical
loops only from the last column item to the first item in the column row.- If
currentId
is initially set tonull
, vertical loop will have no effect as moving down from the last row or up from the first row will focus the composite element. - If
wrap
matches the value ofloop
, it'll wrap between the last item in the last row or column and the first item in the first row or column and vice-versa.
-
wrap
boolean | "horizontal" | "vertical"
Has effect only on two-dimensional composites. If enabled, moving to the next item from the last one in a row or column will focus the first item in the next row or column and vice-versa.
true
wraps between rows and columns.horizontal
wraps only between rows.vertical
wraps only between columns.- If
loop
matches the value ofwrap
, it'll wrap between the last item in the last row or column and the first item in the first row or column and vice-versa.
-
shift
boolean
Has effect only on two-dimensional composites. If enabled, moving up or down when there's no next item or the next item is disabled will shift to the item right before it.
-
unstable_values
{ [x: string]: any; }
Stores the values of radios and checkboxes within the menu.
-
visible
boolean
Whether it's visible or not.
-
animated
number | boolean
If
true
,animating
will be set totrue
whenvisible
is updated. It'll wait forstopAnimation
to be called or a CSS transition ends. Ifanimated
is set to anumber
,stopAnimation
will be called only after the same number of milliseconds have passed. -
modal
boolean
Toggles Dialog's
modal
state.- Non-modal:
preventBodyScroll
doesn't work and focus is free. - Modal:
preventBodyScroll
is automatically enabled, focus is trapped within the dialog and the dialog is rendered within aPortal
by default.
- Non-modal:
-
placement
"auto-start" | "auto" | "auto-end" | "top-start...
Actual
placement
. -
unstable_fixed
boolean | undefined
Whether or not the popover should have
position
set tofixed
. -
unstable_flip
boolean | undefined
Flip the popover's placement when it starts to overlap its reference element.
-
unstable_offset
[string | number, string | number] | undefined
Offset between the reference and the popover: [main axis, alt axis]. Should not be combined with
gutter
. -
gutter
number | undefined
Offset between the reference and the popover on the main axis. Should not be combined with
unstable_offset
. -
unstable_preventOverflow
boolean | undefined
Prevents popover from being positioned outside the boundary.
#Menu
-
hideOnClickOutside
boolean | undefined
When enabled, user can hide the dialog by clicking outside it.
-
preventBodyScroll
boolean | undefined
When enabled, user can't scroll on body when the dialog is visible. This option doesn't work if the dialog isn't modal.
-
unstable_initialFocusRef
RefObject<HTMLElement> | undefined
The element that will be focused when the dialog shows. When not set, the first tabbable element within the dialog will be used.
-
unstable_finalFocusRef
RefObject<HTMLElement> | undefined
The element that will be focused when the dialog hides. When not set, the disclosure component will be used.
-
unstable_orphan
boolean | undefined
Whether or not the dialog should be a child of its parent. Opening a nested orphan dialog will close its parent dialog if
hideOnClickOutside
is set totrue
on the parent. It will be set tofalse
ifmodal
isfalse
. -
disabled
boolean | undefined
Same as the HTML attribute.
-
focusable
boolean | undefined
When an element is
disabled
, it may still befocusable
. It works similarly toreadOnly
on form elements. In this case, onlyaria-disabled
will be set.
21 state props
These props are returned by the state hook. You can spread them into this component (
{...state}
) or pass them separately. You can also provide these props from your own state logic.
-
baseId
string
ID that will serve as a base for all the items IDs.
-
visible
boolean
Whether it's visible or not.
-
animated
number | boolean
If
true
,animating
will be set totrue
whenvisible
is updated. It'll wait forstopAnimation
to be called or a CSS transition ends. Ifanimated
is set to anumber
,stopAnimation
will be called only after the same number of milliseconds have passed. -
modal
boolean
Toggles Dialog's
modal
state.- Non-modal:
preventBodyScroll
doesn't work and focus is free. - Modal:
preventBodyScroll
is automatically enabled, focus is trapped within the dialog and the dialog is rendered within aPortal
by default.
- Non-modal:
-
animating
boolean
Whether it's animating or not.
-
stopAnimation
() => void
Stops animation. It's called automatically if there's a CSS transition.
-
hide
() => void
Changes the
visible
state tofalse
-
placement
"auto-start" | "auto" | "auto-end" | "top-start...
Actual
placement
. -
unstable_virtual
boolean
If enabled, the composite element will act as an aria-activedescendant container instead of roving tabindex. DOM focus will remain on the composite while its items receive virtual focus.
-
orientation
"horizontal" | "vertical" | undefined
Defines the orientation of the composite widget. If the composite has a single row or column (one-dimensional), the
orientation
value determines which arrow keys can be used to move focus:undefined
: all arrow keys work.horizontal
: only left and right arrow keys work.vertical
: only up and down arrow keys work.
It doesn't have any effect on two-dimensional composites.
-
currentId
string | null | undefined
The current focused item
id
.undefined
will automatically focus the first enabled composite item.null
will focus the base composite element and users will be able to navigate out of it using arrow keys.- If
currentId
is initially set tonull
, the base composite element itself will have focus and users will be able to navigate to it using arrow keys.
-
wrap
boolean | "horizontal" | "vertical"
Has effect only on two-dimensional composites. If enabled, moving to the next item from the last one in a row or column will focus the first item in the next row or column and vice-versa.
true
wraps between rows and columns.horizontal
wraps only between rows.vertical
wraps only between columns.- If
loop
matches the value ofwrap
, it'll wrap between the last item in the last row or column and the first item in the first row or column and vice-versa.
-
unstable_moves
number
Stores the number of moves that have been performed by calling
move
,next
,previous
,up
,down
,first
orlast
. -
groups
Group[]
Lists all the composite groups with their
id
and DOMref
. This state is automatically updated whenregisterGroup
andunregisterGroup
are called. -
items
Item[]
Lists all the composite items with their
id
, DOMref
,disabled
state andgroupId
if any. This state is automatically updated whenregisterItem
andunregisterItem
are called. -
setCurrentId
(value: SetStateAction<string | null | undefine...
Sets
currentId
. This is different fromcomposite.move
as this only updates thecurrentId
state without moving focus. When the composite widget gets focused by the user, the item referred by thecurrentId
state will get focus. -
first
() => void
Moves focus to the first item.
-
last
() => void
Moves focus to the last item.
-
move
(id: string | null) => void
Moves focus to a given item ID.
-
next
(unstable_allTheWay?: boolean | undefined) => void
Moves focus to the next item.
-
previous
(unstable_allTheWay?: boolean | undefined) => void
Moves focus to the previous item.
#MenuArrow
-
size
string | number | undefined
Arrow's size
1 state props
These props are returned by the state hook. You can spread them into this component (
{...state}
) or pass them separately. You can also provide these props from your own state logic.
-
placement
"auto-start" | "auto" | "auto-end" | "top-start...
Actual
placement
.
#MenuBar
-
disabled
boolean | undefined
Same as the HTML attribute.
-
focusable
boolean | undefined
When an element is
disabled
, it may still befocusable
. It works similarly toreadOnly
on form elements. In this case, onlyaria-disabled
will be set.
14 state props
These props are returned by the state hook. You can spread them into this component (
{...state}
) or pass them separately. You can also provide these props from your own state logic.
-
baseId
string
ID that will serve as a base for all the items IDs.
-
unstable_virtual
boolean
If enabled, the composite element will act as an aria-activedescendant container instead of roving tabindex. DOM focus will remain on the composite while its items receive virtual focus.
-
orientation
"horizontal" | "vertical" | undefined
Defines the orientation of the composite widget. If the composite has a single row or column (one-dimensional), the
orientation
value determines which arrow keys can be used to move focus:undefined
: all arrow keys work.horizontal
: only left and right arrow keys work.vertical
: only up and down arrow keys work.
It doesn't have any effect on two-dimensional composites.
-
currentId
string | null | undefined
The current focused item
id
.undefined
will automatically focus the first enabled composite item.null
will focus the base composite element and users will be able to navigate out of it using arrow keys.- If
currentId
is initially set tonull
, the base composite element itself will have focus and users will be able to navigate to it using arrow keys.
-
wrap
boolean | "horizontal" | "vertical"
Has effect only on two-dimensional composites. If enabled, moving to the next item from the last one in a row or column will focus the first item in the next row or column and vice-versa.
true
wraps between rows and columns.horizontal
wraps only between rows.vertical
wraps only between columns.- If
loop
matches the value ofwrap
, it'll wrap between the last item in the last row or column and the first item in the first row or column and vice-versa.
-
unstable_moves
number
Stores the number of moves that have been performed by calling
move
,next
,previous
,up
,down
,first
orlast
. -
groups
Group[]
Lists all the composite groups with their
id
and DOMref
. This state is automatically updated whenregisterGroup
andunregisterGroup
are called. -
items
Item[]
Lists all the composite items with their
id
, DOMref
,disabled
state andgroupId
if any. This state is automatically updated whenregisterItem
andunregisterItem
are called. -
setCurrentId
(value: SetStateAction<string | null | undefine...
Sets
currentId
. This is different fromcomposite.move
as this only updates thecurrentId
state without moving focus. When the composite widget gets focused by the user, the item referred by thecurrentId
state will get focus. -
first
() => void
Moves focus to the first item.
-
last
() => void
Moves focus to the last item.
-
move
(id: string | null) => void
Moves focus to a given item ID.
-
next
(unstable_allTheWay?: boolean | undefined) => void
Moves focus to the next item.
-
previous
(unstable_allTheWay?: boolean | undefined) => void
Moves focus to the previous item.
#MenuButton
-
disabled
boolean | undefined
Same as the HTML attribute.
-
focusable
boolean | undefined
When an element is
disabled
, it may still befocusable
. It works similarly toreadOnly
on form elements. In this case, onlyaria-disabled
will be set.
12 state props
These props are returned by the state hook. You can spread them into this component (
{...state}
) or pass them separately. You can also provide these props from your own state logic.
-
visible
boolean
Whether it's visible or not.
-
baseId
string
ID that will serve as a base for all the items IDs.
-
toggle
() => void
Toggles the
visible
state -
unstable_referenceRef
RefObject<HTMLElement | null>
The reference element.
-
currentId
string | null | undefined
The current focused item
id
.undefined
will automatically focus the first enabled composite item.null
will focus the base composite element and users will be able to navigate out of it using arrow keys.- If
currentId
is initially set tonull
, the base composite element itself will have focus and users will be able to navigate to it using arrow keys.
-
hide
() => void
Changes the
visible
state tofalse
-
unstable_moves
number
Stores the number of moves that have been performed by calling
move
,next
,previous
,up
,down
,first
orlast
. -
move
(id: string | null) => void
Moves focus to a given item ID.
-
placement
"auto-start" | "auto" | "auto-end" | "top-start...
Actual
placement
. -
show
() => void
Changes the
visible
state totrue
-
first
() => void
Moves focus to the first item.
-
last
() => void
Moves focus to the last item.
#MenuDisclosure
-
disabled
boolean | undefined
Same as the HTML attribute.
-
focusable
boolean | undefined
When an element is
disabled
, it may still befocusable
. It works similarly toreadOnly
on form elements. In this case, onlyaria-disabled
will be set.
12 state props
These props are returned by the state hook. You can spread them into this component (
{...state}
) or pass them separately. You can also provide these props from your own state logic.
-
visible
boolean
Whether it's visible or not.
-
baseId
string
ID that will serve as a base for all the items IDs.
-
toggle
() => void
Toggles the
visible
state -
unstable_referenceRef
RefObject<HTMLElement | null>
The reference element.
-
currentId
string | null | undefined
The current focused item
id
.undefined
will automatically focus the first enabled composite item.null
will focus the base composite element and users will be able to navigate out of it using arrow keys.- If
currentId
is initially set tonull
, the base composite element itself will have focus and users will be able to navigate to it using arrow keys.
-
hide
() => void
Changes the
visible
state tofalse
-
unstable_moves
number
Stores the number of moves that have been performed by calling
move
,next
,previous
,up
,down
,first
orlast
. -
move
(id: string | null) => void
Moves focus to a given item ID.
-
placement
"auto-start" | "auto" | "auto-end" | "top-start...
Actual
placement
. -
show
() => void
Changes the
visible
state totrue
-
first
() => void
Moves focus to the first item.
-
last
() => void
Moves focus to the last item.
#MenuGroup
No props to show
#MenuItem
-
disabled
boolean | undefined
Same as the HTML attribute.
-
focusable
boolean | undefined
When an element is
disabled
, it may still befocusable
. It works similarly toreadOnly
on form elements. In this case, onlyaria-disabled
will be set. -
id
string | undefined
Same as the HTML attribute.
19 state props
These props are returned by the state hook. You can spread them into this component (
{...state}
) or pass them separately. You can also provide these props from your own state logic.
-
baseId
string
ID that will serve as a base for all the items IDs.
-
unstable_virtual
boolean
If enabled, the composite element will act as an aria-activedescendant container instead of roving tabindex. DOM focus will remain on the composite while its items receive virtual focus.
-
orientation
"horizontal" | "vertical" | undefined
Defines the orientation of the composite widget. If the composite has a single row or column (one-dimensional), the
orientation
value determines which arrow keys can be used to move focus:undefined
: all arrow keys work.horizontal
: only left and right arrow keys work.vertical
: only up and down arrow keys work.
It doesn't have any effect on two-dimensional composites.
-
unstable_moves
number
Stores the number of moves that have been performed by calling
move
,next
,previous
,up
,down
,first
orlast
. -
currentId
string | null | undefined
The current focused item
id
.undefined
will automatically focus the first enabled composite item.null
will focus the base composite element and users will be able to navigate out of it using arrow keys.- If
currentId
is initially set tonull
, the base composite element itself will have focus and users will be able to navigate to it using arrow keys.
-
items
Item[]
Lists all the composite items with their
id
, DOMref
,disabled
state andgroupId
if any. This state is automatically updated whenregisterItem
andunregisterItem
are called. -
setCurrentId
(value: SetStateAction<string | null | undefine...
Sets
currentId
. This is different fromcomposite.move
as this only updates thecurrentId
state without moving focus. When the composite widget gets focused by the user, the item referred by thecurrentId
state will get focus. -
first
() => void
Moves focus to the first item.
-
last
() => void
Moves focus to the last item.
-
next
(unstable_allTheWay?: boolean | undefined) => void
Moves focus to the next item.
-
previous
(unstable_allTheWay?: boolean | undefined) => void
Moves focus to the previous item.
-
registerItem
(item: Item) => void
Registers a composite item.
-
unregisterItem
(id: string) => void
Unregisters a composite item.
-
up
(unstable_allTheWay?: boolean | undefined) => void
Moves focus to the item above.
-
down
(unstable_allTheWay?: boolean | undefined) => void
Moves focus to the item below.
-
visible
boolean
Whether it's visible or not.
-
placement
"auto-start" | "auto" | "auto-end" | "top-start...
Actual
placement
. -
hide
() => void
Changes the
visible
state tofalse
-
move
(id: string | null) => void
Moves focus to a given item ID.
#MenuItemCheckbox
-
disabled
boolean | undefined
Same as the HTML attribute.
-
focusable
boolean | undefined
When an element is
disabled
, it may still befocusable
. It works similarly toreadOnly
on form elements. In this case, onlyaria-disabled
will be set. -
value
string | number | undefined
Checkbox's value is going to be used when multiple checkboxes share the same state. Checking a checkbox with value will add it to the state array.
-
checked
boolean | undefined
Checkbox's checked state. If present, it's used instead of
state
. -
id
string | undefined
Same as the HTML attribute.
-
name
string
MenuItemCheckbox's name as in
menu.values
.
23 state props
These props are returned by the state hook. You can spread them into this component (
{...state}
) or pass them separately. You can also provide these props from your own state logic.
-
state
boolean | "indeterminate" | (string | number)[]
Stores the state of the checkbox. If checkboxes that share this state have defined a
value
prop, it's going to be an array. -
setState
(value: SetStateAction<boolean | "indeterminate...
Sets
state
. -
baseId
string
ID that will serve as a base for all the items IDs.
-
unstable_virtual
boolean
If enabled, the composite element will act as an aria-activedescendant container instead of roving tabindex. DOM focus will remain on the composite while its items receive virtual focus.
-
orientation
"horizontal" | "vertical" | undefined
Defines the orientation of the composite widget. If the composite has a single row or column (one-dimensional), the
orientation
value determines which arrow keys can be used to move focus:undefined
: all arrow keys work.horizontal
: only left and right arrow keys work.vertical
: only up and down arrow keys work.
It doesn't have any effect on two-dimensional composites.
-
unstable_moves
number
Stores the number of moves that have been performed by calling
move
,next
,previous
,up
,down
,first
orlast
. -
currentId
string | null | undefined
The current focused item
id
.undefined
will automatically focus the first enabled composite item.null
will focus the base composite element and users will be able to navigate out of it using arrow keys.- If
currentId
is initially set tonull
, the base composite element itself will have focus and users will be able to navigate to it using arrow keys.
-
items
Item[]
Lists all the composite items with their
id
, DOMref
,disabled
state andgroupId
if any. This state is automatically updated whenregisterItem
andunregisterItem
are called. -
setCurrentId
(value: SetStateAction<string | null | undefine...
Sets
currentId
. This is different fromcomposite.move
as this only updates thecurrentId
state without moving focus. When the composite widget gets focused by the user, the item referred by thecurrentId
state will get focus. -
first
() => void
Moves focus to the first item.
-
last
() => void
Moves focus to the last item.
-
next
(unstable_allTheWay?: boolean | undefined) => void
Moves focus to the next item.
-
previous
(unstable_allTheWay?: boolean | undefined) => void
Moves focus to the previous item.
-
registerItem
(item: Item) => void
Registers a composite item.
-
unregisterItem
(id: string) => void
Unregisters a composite item.
-
up
(unstable_allTheWay?: boolean | undefined) => void
Moves focus to the item above.
-
down
(unstable_allTheWay?: boolean | undefined) => void
Moves focus to the item below.
-
visible
boolean
Whether it's visible or not.
-
placement
"auto-start" | "auto" | "auto-end" | "top-start...
Actual
placement
. -
hide
() => void
Changes the
visible
state tofalse
-
move
(id: string | null) => void
Moves focus to a given item ID.
-
unstable_values
{ [x: string]: any; }
Stores the values of radios and checkboxes within the menu.
-
unstable_setValue
(name: string, value?: any) => void
Updates checkboxes and radios values within the menu.
#MenuItemRadio
-
disabled
boolean | undefined
Same as the HTML attribute.
-
focusable
boolean | undefined
When an element is
disabled
, it may still befocusable
. It works similarly toreadOnly
on form elements. In this case, onlyaria-disabled
will be set. -
id
string | undefined
Same as the HTML attribute.
-
value
string | number
Same as the
value
attribute. -
checked
boolean | undefined
Same as the
checked
attribute. -
name
string
MenuItemRadio's name as in
menu.values
.
23 state props
These props are returned by the state hook. You can spread them into this component (
{...state}
) or pass them separately. You can also provide these props from your own state logic.
-
baseId
string
ID that will serve as a base for all the items IDs.
-
unstable_virtual
boolean
If enabled, the composite element will act as an aria-activedescendant container instead of roving tabindex. DOM focus will remain on the composite while its items receive virtual focus.
-
orientation
"horizontal" | "vertical" | undefined
Defines the orientation of the composite widget. If the composite has a single row or column (one-dimensional), the
orientation
value determines which arrow keys can be used to move focus:undefined
: all arrow keys work.horizontal
: only left and right arrow keys work.vertical
: only up and down arrow keys work.
It doesn't have any effect on two-dimensional composites.
-
unstable_moves
number
Stores the number of moves that have been performed by calling
move
,next
,previous
,up
,down
,first
orlast
. -
currentId
string | null | undefined
The current focused item
id
.undefined
will automatically focus the first enabled composite item.null
will focus the base composite element and users will be able to navigate out of it using arrow keys.- If
currentId
is initially set tonull
, the base composite element itself will have focus and users will be able to navigate to it using arrow keys.
-
items
Item[]
Lists all the composite items with their
id
, DOMref
,disabled
state andgroupId
if any. This state is automatically updated whenregisterItem
andunregisterItem
are called. -
setCurrentId
(value: SetStateAction<string | null | undefine...
Sets
currentId
. This is different fromcomposite.move
as this only updates thecurrentId
state without moving focus. When the composite widget gets focused by the user, the item referred by thecurrentId
state will get focus. -
first
() => void
Moves focus to the first item.
-
last
() => void
Moves focus to the last item.
-
next
(unstable_allTheWay?: boolean | undefined) => void
Moves focus to the next item.
-
previous
(unstable_allTheWay?: boolean | undefined) => void
Moves focus to the previous item.
-
registerItem
(item: Item) => void
Registers a composite item.
-
unregisterItem
(id: string) => void
Unregisters a composite item.
-
up
(unstable_allTheWay?: boolean | undefined) => void
Moves focus to the item above.
-
down
(unstable_allTheWay?: boolean | undefined) => void
Moves focus to the item below.
-
state
string | number | undefined
The
value
attribute of the current checked radio. -
setState
(value: SetStateAction<string | number | undefi...
Sets
state
. -
visible
boolean
Whether it's visible or not.
-
placement
"auto-start" | "auto" | "auto-end" | "top-start...
Actual
placement
. -
hide
() => void
Changes the
visible
state tofalse
-
move
(id: string | null) => void
Moves focus to a given item ID.
-
unstable_values
{ [x: string]: any; }
Stores the values of radios and checkboxes within the menu.
-
unstable_setValue
(name: string, value?: any) => void
Updates checkboxes and radios values within the menu.
#MenuSeparator
1 state props
These props are returned by the state hook. You can spread them into this component (
{...state}
) or pass them separately. You can also provide these props from your own state logic.
-
orientation
"horizontal" | "vertical" | undefined
Separator's orientation.