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 Menus 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 MenuItems, you can do the following:
- Pass an
idprop to eachMenuItem. - Memoize all non-primitive props that you're passing to
MenuItem, including event handlers (e.g.onClick) and thechildrenprop.
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
Menuhas rolemenu.MenuBarhas rolemenubar.MenuandMenuBarextend the accessibility features of Composite.MenuButtonextends the accessibility features of PopoverDisclosure, which means it setsaria-haspopupandaria-expandedattributes accordingly.MenuItemhas rolemenuitem.MenuItemextends the accessibility features of CompositeItem, which means it uses the roving tabindex method to manage focus.MenuItemCheckboxhas rolemenuitemcheckbox.MenuItemRadiohas rolemenuitemradio.- Pressing Enter on
MenuButtonopens its menu (or submenu) and places focus on its first item. - Pressing Space on
MenuItemCheckboxchanges the state without closingMenu. - Pressing Space on a
MenuItemRadiothat is not checked, without closingMenu, checks the focusedMenuItemRadioand unchecks any other checkedMenuItemRadioin the same group. - Pressing any key that corresponds to a printable character moves focus to the next
MenuItemin the currentMenuorMenuBarwhose label begins with that printable character.
Learn more in Accessibility.
#Composition
MenuusesMenuBarand Popover.MenuArrowuses PopoverArrow.MenuButtonuses PopoverDisclosure.MenuGroupuses Role.MenuItemuses CompositeItem.MenuItemCheckboxusesMenuItemand Checkbox.MenuItemRadiousesMenuItemand Radio.MenuSeparatoruses Separator.MenuBaruses Composite.
Learn more in Composition.
#Props
#useMenuBarState
-
baseIdstringID that will serve as a base for all the items IDs.
-
unstable_virtualbooleanIf 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.
-
rtlbooleanDetermines how
nextandpreviousfunctions will behave. Ifrtlis 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" | undefinedDefines the orientation of the composite widget. If the composite has a single row or column (one-dimensional), the
orientationvalue 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.
-
currentIdstring | null | undefinedThe current focused item
id.undefinedwill automatically focus the first enabled composite item.nullwill focus the base composite element and users will be able to navigate out of it using arrow keys.- If
currentIdis initially set tonull, the base composite element itself will have focus and users will be able to navigate to it using arrow keys.
-
loopboolean | "horizontal" | "vertical"On one-dimensional composites:
trueloops from the last item to the first item and vice-versa.horizontalloops only iforientationishorizontalor not set.verticalloops only iforientationisverticalor not set.- If
currentIdis initially set tonull, the composite element will be focused in between the last and first items.
On two-dimensional composites:
trueloops 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.horizontalloops only from the last row item to the first item in the same row.verticalloops only from the last column item to the first item in the column row.- If
currentIdis 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
wrapmatches 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.
-
wrapboolean | "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.
truewraps between rows and columns.horizontalwraps only between rows.verticalwraps only between columns.- If
loopmatches 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.
-
shiftbooleanHas 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
-
baseIdstringID that will serve as a base for all the items IDs.
-
unstable_virtualbooleanIf 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.
-
rtlbooleanDetermines how
nextandpreviousfunctions will behave. Ifrtlis 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" | undefinedDefines the orientation of the composite widget. If the composite has a single row or column (one-dimensional), the
orientationvalue 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.
-
currentIdstring | null | undefinedThe current focused item
id.undefinedwill automatically focus the first enabled composite item.nullwill focus the base composite element and users will be able to navigate out of it using arrow keys.- If
currentIdis initially set tonull, the base composite element itself will have focus and users will be able to navigate to it using arrow keys.
-
loopboolean | "horizontal" | "vertical"On one-dimensional composites:
trueloops from the last item to the first item and vice-versa.horizontalloops only iforientationishorizontalor not set.verticalloops only iforientationisverticalor not set.- If
currentIdis initially set tonull, the composite element will be focused in between the last and first items.
On two-dimensional composites:
trueloops 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.horizontalloops only from the last row item to the first item in the same row.verticalloops only from the last column item to the first item in the column row.- If
currentIdis 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
wrapmatches 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.
-
wrapboolean | "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.
truewraps between rows and columns.horizontalwraps only between rows.verticalwraps only between columns.- If
loopmatches 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.
-
shiftbooleanHas 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.
-
visiblebooleanWhether it's visible or not.
-
animatednumber | booleanIf
true,animatingwill be set totruewhenvisibleis updated. It'll wait forstopAnimationto be called or a CSS transition ends. Ifanimatedis set to anumber,stopAnimationwill be called only after the same number of milliseconds have passed. -
modalbooleanToggles Dialog's
modalstate.- Non-modal:
preventBodyScrolldoesn't work and focus is free. - Modal:
preventBodyScrollis automatically enabled, focus is trapped within the dialog and the dialog is rendered within aPortalby default.
- Non-modal:
-
placement"auto-start" | "auto" | "auto-end" | "top-start...Actual
placement. -
unstable_fixedboolean | undefinedWhether or not the popover should have
positionset tofixed. -
unstable_flipboolean | undefinedFlip the popover's placement when it starts to overlap its reference element.
-
unstable_offset[string | number, string | number] | undefinedOffset between the reference and the popover: [main axis, alt axis]. Should not be combined with
gutter. -
gutternumber | undefinedOffset between the reference and the popover on the main axis. Should not be combined with
unstable_offset. -
unstable_preventOverflowboolean | undefinedPrevents popover from being positioned outside the boundary.
#Menu
-
hideOnClickOutsideboolean | undefinedWhen enabled, user can hide the dialog by clicking outside it.
-
preventBodyScrollboolean | undefinedWhen enabled, user can't scroll on body when the dialog is visible. This option doesn't work if the dialog isn't modal.
-
unstable_initialFocusRefRefObject<HTMLElement> | undefinedThe element that will be focused when the dialog shows. When not set, the first tabbable element within the dialog will be used.
-
unstable_finalFocusRefRefObject<HTMLElement> | undefinedThe element that will be focused when the dialog hides. When not set, the disclosure component will be used.
-
unstable_orphanboolean | undefinedWhether or not the dialog should be a child of its parent. Opening a nested orphan dialog will close its parent dialog if
hideOnClickOutsideis set totrueon the parent. It will be set tofalseifmodalisfalse. -
disabledboolean | undefinedSame as the HTML attribute.
-
focusableboolean | undefinedWhen an element is
disabled, it may still befocusable. It works similarly toreadOnlyon form elements. In this case, onlyaria-disabledwill 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.
-
baseIdstringID that will serve as a base for all the items IDs.
-
visiblebooleanWhether it's visible or not.
-
animatednumber | booleanIf
true,animatingwill be set totruewhenvisibleis updated. It'll wait forstopAnimationto be called or a CSS transition ends. Ifanimatedis set to anumber,stopAnimationwill be called only after the same number of milliseconds have passed. -
modalbooleanToggles Dialog's
modalstate.- Non-modal:
preventBodyScrolldoesn't work and focus is free. - Modal:
preventBodyScrollis automatically enabled, focus is trapped within the dialog and the dialog is rendered within aPortalby default.
- Non-modal:
-
animatingbooleanWhether it's animating or not.
-
stopAnimation() => voidStops animation. It's called automatically if there's a CSS transition.
-
hide() => voidChanges the
visiblestate tofalse -
placement"auto-start" | "auto" | "auto-end" | "top-start...Actual
placement. -
unstable_virtualbooleanIf 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" | undefinedDefines the orientation of the composite widget. If the composite has a single row or column (one-dimensional), the
orientationvalue 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.
-
currentIdstring | null | undefinedThe current focused item
id.undefinedwill automatically focus the first enabled composite item.nullwill focus the base composite element and users will be able to navigate out of it using arrow keys.- If
currentIdis initially set tonull, the base composite element itself will have focus and users will be able to navigate to it using arrow keys.
-
wrapboolean | "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.
truewraps between rows and columns.horizontalwraps only between rows.verticalwraps only between columns.- If
loopmatches 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_movesnumberStores the number of moves that have been performed by calling
move,next,previous,up,down,firstorlast. -
groupsGroup[]Lists all the composite groups with their
idand DOMref. This state is automatically updated whenregisterGroupandunregisterGroupare called. -
itemsItem[]Lists all the composite items with their
id, DOMref,disabledstate andgroupIdif any. This state is automatically updated whenregisterItemandunregisterItemare called. -
setCurrentId(value: SetStateAction<string | null | undefine...Sets
currentId. This is different fromcomposite.moveas this only updates thecurrentIdstate without moving focus. When the composite widget gets focused by the user, the item referred by thecurrentIdstate will get focus. -
first() => voidMoves focus to the first item.
-
last() => voidMoves focus to the last item.
-
move(id: string | null) => voidMoves focus to a given item ID.
-
next(unstable_allTheWay?: boolean | undefined) => voidMoves focus to the next item.
-
previous(unstable_allTheWay?: boolean | undefined) => voidMoves focus to the previous item.
#MenuArrow
-
sizestring | number | undefinedArrow'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
-
disabledboolean | undefinedSame as the HTML attribute.
-
focusableboolean | undefinedWhen an element is
disabled, it may still befocusable. It works similarly toreadOnlyon form elements. In this case, onlyaria-disabledwill 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.
-
baseIdstringID that will serve as a base for all the items IDs.
-
unstable_virtualbooleanIf 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" | undefinedDefines the orientation of the composite widget. If the composite has a single row or column (one-dimensional), the
orientationvalue 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.
-
currentIdstring | null | undefinedThe current focused item
id.undefinedwill automatically focus the first enabled composite item.nullwill focus the base composite element and users will be able to navigate out of it using arrow keys.- If
currentIdis initially set tonull, the base composite element itself will have focus and users will be able to navigate to it using arrow keys.
-
wrapboolean | "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.
truewraps between rows and columns.horizontalwraps only between rows.verticalwraps only between columns.- If
loopmatches 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_movesnumberStores the number of moves that have been performed by calling
move,next,previous,up,down,firstorlast. -
groupsGroup[]Lists all the composite groups with their
idand DOMref. This state is automatically updated whenregisterGroupandunregisterGroupare called. -
itemsItem[]Lists all the composite items with their
id, DOMref,disabledstate andgroupIdif any. This state is automatically updated whenregisterItemandunregisterItemare called. -
setCurrentId(value: SetStateAction<string | null | undefine...Sets
currentId. This is different fromcomposite.moveas this only updates thecurrentIdstate without moving focus. When the composite widget gets focused by the user, the item referred by thecurrentIdstate will get focus. -
first() => voidMoves focus to the first item.
-
last() => voidMoves focus to the last item.
-
move(id: string | null) => voidMoves focus to a given item ID.
-
next(unstable_allTheWay?: boolean | undefined) => voidMoves focus to the next item.
-
previous(unstable_allTheWay?: boolean | undefined) => voidMoves focus to the previous item.
#MenuButton
-
disabledboolean | undefinedSame as the HTML attribute.
-
focusableboolean | undefinedWhen an element is
disabled, it may still befocusable. It works similarly toreadOnlyon form elements. In this case, onlyaria-disabledwill 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.
-
visiblebooleanWhether it's visible or not.
-
baseIdstringID that will serve as a base for all the items IDs.
-
toggle() => voidToggles the
visiblestate -
unstable_referenceRefRefObject<HTMLElement | null>The reference element.
-
currentIdstring | null | undefinedThe current focused item
id.undefinedwill automatically focus the first enabled composite item.nullwill focus the base composite element and users will be able to navigate out of it using arrow keys.- If
currentIdis initially set tonull, the base composite element itself will have focus and users will be able to navigate to it using arrow keys.
-
hide() => voidChanges the
visiblestate tofalse -
unstable_movesnumberStores the number of moves that have been performed by calling
move,next,previous,up,down,firstorlast. -
move(id: string | null) => voidMoves focus to a given item ID.
-
placement"auto-start" | "auto" | "auto-end" | "top-start...Actual
placement. -
show() => voidChanges the
visiblestate totrue -
first() => voidMoves focus to the first item.
-
last() => voidMoves focus to the last item.
#MenuDisclosure
-
disabledboolean | undefinedSame as the HTML attribute.
-
focusableboolean | undefinedWhen an element is
disabled, it may still befocusable. It works similarly toreadOnlyon form elements. In this case, onlyaria-disabledwill 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.
-
visiblebooleanWhether it's visible or not.
-
baseIdstringID that will serve as a base for all the items IDs.
-
toggle() => voidToggles the
visiblestate -
unstable_referenceRefRefObject<HTMLElement | null>The reference element.
-
currentIdstring | null | undefinedThe current focused item
id.undefinedwill automatically focus the first enabled composite item.nullwill focus the base composite element and users will be able to navigate out of it using arrow keys.- If
currentIdis initially set tonull, the base composite element itself will have focus and users will be able to navigate to it using arrow keys.
-
hide() => voidChanges the
visiblestate tofalse -
unstable_movesnumberStores the number of moves that have been performed by calling
move,next,previous,up,down,firstorlast. -
move(id: string | null) => voidMoves focus to a given item ID.
-
placement"auto-start" | "auto" | "auto-end" | "top-start...Actual
placement. -
show() => voidChanges the
visiblestate totrue -
first() => voidMoves focus to the first item.
-
last() => voidMoves focus to the last item.
#MenuGroup
No props to show
#MenuItem
-
disabledboolean | undefinedSame as the HTML attribute.
-
focusableboolean | undefinedWhen an element is
disabled, it may still befocusable. It works similarly toreadOnlyon form elements. In this case, onlyaria-disabledwill be set. -
idstring | undefinedSame 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.
-
baseIdstringID that will serve as a base for all the items IDs.
-
unstable_virtualbooleanIf 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" | undefinedDefines the orientation of the composite widget. If the composite has a single row or column (one-dimensional), the
orientationvalue 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_movesnumberStores the number of moves that have been performed by calling
move,next,previous,up,down,firstorlast. -
currentIdstring | null | undefinedThe current focused item
id.undefinedwill automatically focus the first enabled composite item.nullwill focus the base composite element and users will be able to navigate out of it using arrow keys.- If
currentIdis initially set tonull, the base composite element itself will have focus and users will be able to navigate to it using arrow keys.
-
itemsItem[]Lists all the composite items with their
id, DOMref,disabledstate andgroupIdif any. This state is automatically updated whenregisterItemandunregisterItemare called. -
setCurrentId(value: SetStateAction<string | null | undefine...Sets
currentId. This is different fromcomposite.moveas this only updates thecurrentIdstate without moving focus. When the composite widget gets focused by the user, the item referred by thecurrentIdstate will get focus. -
first() => voidMoves focus to the first item.
-
last() => voidMoves focus to the last item.
-
next(unstable_allTheWay?: boolean | undefined) => voidMoves focus to the next item.
-
previous(unstable_allTheWay?: boolean | undefined) => voidMoves focus to the previous item.
-
registerItem(item: Item) => voidRegisters a composite item.
-
unregisterItem(id: string) => voidUnregisters a composite item.
-
up(unstable_allTheWay?: boolean | undefined) => voidMoves focus to the item above.
-
down(unstable_allTheWay?: boolean | undefined) => voidMoves focus to the item below.
-
visiblebooleanWhether it's visible or not.
-
placement"auto-start" | "auto" | "auto-end" | "top-start...Actual
placement. -
hide() => voidChanges the
visiblestate tofalse -
move(id: string | null) => voidMoves focus to a given item ID.
#MenuItemCheckbox
-
disabledboolean | undefinedSame as the HTML attribute.
-
focusableboolean | undefinedWhen an element is
disabled, it may still befocusable. It works similarly toreadOnlyon form elements. In this case, onlyaria-disabledwill be set. -
valuestring | number | undefinedCheckbox'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.
-
checkedboolean | undefinedCheckbox's checked state. If present, it's used instead of
state. -
idstring | undefinedSame as the HTML attribute.
-
namestringMenuItemCheckbox'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.
-
stateboolean | "indeterminate" | (string | number)[]Stores the state of the checkbox. If checkboxes that share this state have defined a
valueprop, it's going to be an array. -
setState(value: SetStateAction<boolean | "indeterminate...Sets
state. -
baseIdstringID that will serve as a base for all the items IDs.
-
unstable_virtualbooleanIf 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" | undefinedDefines the orientation of the composite widget. If the composite has a single row or column (one-dimensional), the
orientationvalue 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_movesnumberStores the number of moves that have been performed by calling
move,next,previous,up,down,firstorlast. -
currentIdstring | null | undefinedThe current focused item
id.undefinedwill automatically focus the first enabled composite item.nullwill focus the base composite element and users will be able to navigate out of it using arrow keys.- If
currentIdis initially set tonull, the base composite element itself will have focus and users will be able to navigate to it using arrow keys.
-
itemsItem[]Lists all the composite items with their
id, DOMref,disabledstate andgroupIdif any. This state is automatically updated whenregisterItemandunregisterItemare called. -
setCurrentId(value: SetStateAction<string | null | undefine...Sets
currentId. This is different fromcomposite.moveas this only updates thecurrentIdstate without moving focus. When the composite widget gets focused by the user, the item referred by thecurrentIdstate will get focus. -
first() => voidMoves focus to the first item.
-
last() => voidMoves focus to the last item.
-
next(unstable_allTheWay?: boolean | undefined) => voidMoves focus to the next item.
-
previous(unstable_allTheWay?: boolean | undefined) => voidMoves focus to the previous item.
-
registerItem(item: Item) => voidRegisters a composite item.
-
unregisterItem(id: string) => voidUnregisters a composite item.
-
up(unstable_allTheWay?: boolean | undefined) => voidMoves focus to the item above.
-
down(unstable_allTheWay?: boolean | undefined) => voidMoves focus to the item below.
-
visiblebooleanWhether it's visible or not.
-
placement"auto-start" | "auto" | "auto-end" | "top-start...Actual
placement. -
hide() => voidChanges the
visiblestate tofalse -
move(id: string | null) => voidMoves 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) => voidUpdates checkboxes and radios values within the menu.
#MenuItemRadio
-
disabledboolean | undefinedSame as the HTML attribute.
-
focusableboolean | undefinedWhen an element is
disabled, it may still befocusable. It works similarly toreadOnlyon form elements. In this case, onlyaria-disabledwill be set. -
idstring | undefinedSame as the HTML attribute.
-
valuestring | numberSame as the
valueattribute. -
checkedboolean | undefinedSame as the
checkedattribute. -
namestringMenuItemRadio'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.
-
baseIdstringID that will serve as a base for all the items IDs.
-
unstable_virtualbooleanIf 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" | undefinedDefines the orientation of the composite widget. If the composite has a single row or column (one-dimensional), the
orientationvalue 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_movesnumberStores the number of moves that have been performed by calling
move,next,previous,up,down,firstorlast. -
currentIdstring | null | undefinedThe current focused item
id.undefinedwill automatically focus the first enabled composite item.nullwill focus the base composite element and users will be able to navigate out of it using arrow keys.- If
currentIdis initially set tonull, the base composite element itself will have focus and users will be able to navigate to it using arrow keys.
-
itemsItem[]Lists all the composite items with their
id, DOMref,disabledstate andgroupIdif any. This state is automatically updated whenregisterItemandunregisterItemare called. -
setCurrentId(value: SetStateAction<string | null | undefine...Sets
currentId. This is different fromcomposite.moveas this only updates thecurrentIdstate without moving focus. When the composite widget gets focused by the user, the item referred by thecurrentIdstate will get focus. -
first() => voidMoves focus to the first item.
-
last() => voidMoves focus to the last item.
-
next(unstable_allTheWay?: boolean | undefined) => voidMoves focus to the next item.
-
previous(unstable_allTheWay?: boolean | undefined) => voidMoves focus to the previous item.
-
registerItem(item: Item) => voidRegisters a composite item.
-
unregisterItem(id: string) => voidUnregisters a composite item.
-
up(unstable_allTheWay?: boolean | undefined) => voidMoves focus to the item above.
-
down(unstable_allTheWay?: boolean | undefined) => voidMoves focus to the item below.
-
statestring | number | undefinedThe
valueattribute of the current checked radio. -
setState(value: SetStateAction<string | number | undefi...Sets
state. -
visiblebooleanWhether it's visible or not.
-
placement"auto-start" | "auto" | "auto-end" | "top-start...Actual
placement. -
hide() => voidChanges the
visiblestate tofalse -
move(id: string | null) => voidMoves 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) => voidUpdates 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" | undefinedSeparator's orientation.