Black Lives Matter.  Support the Equal Justice Initiative.
Skip to main content
Reakit
DocumentationNewsletter
GitHub
GitHub

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>
    </>
  );
}

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>
    </>
  );
}

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>
    </>
  );
}

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>
    </>
  );
}

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.

import React from "react";
import {
  useMenuState,
  Menu as BaseMenu,
  MenuItem,
  MenuButton,
} from "reakit/Menu";

function Menu({ disclosure, items, ...props }) {
  const menu = useMenuState();
  return (
    <>
      <MenuButton {...menu} ref={disclosure.ref} {...disclosure.props}>
        {(disclosureProps) => React.cloneElement(disclosure, disclosureProps)}
      </MenuButton>
      <BaseMenu {...menu} {...props}>
        {items.map((item, i) => (
          <MenuItem {...menu} {...item.props} key={i}>
            {(itemProps) => React.cloneElement(item, itemProps)}
          </MenuItem>
        ))}
      </BaseMenu>
    </>
  );
}

function Example() {
  return (
    <Menu
      aria-label="Custom menu"
      disclosure={<button>Custom menu</button>}
      items={[
        <button>Custom item 1</button>,
        <button>Custom item 2</button>,
        <button>Custom item 3</button>,
      ]}
    />
  );
}

#Performance

If you notice performance issues when rendering several MenuItems, you can do the following:

  1. Pass an id prop to each MenuItem.
  2. Memoize all non-primitive props that you're passing to MenuItem, including event handlers (e.g. onClick) and the children 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 role menu.
  • MenuBar has role menubar.
  • Menu and MenuBar extend the accessibility features of Composite.
  • MenuButton extends the accessibility features of PopoverDisclosure, which means it sets aria-haspopup and aria-expanded attributes accordingly.
  • MenuItem has role menuitem.
  • MenuItem extends the accessibility features of CompositeItem, which means it uses the roving tabindex method to manage focus.
  • MenuItemCheckbox has role menuitemcheckbox.
  • MenuItemRadio has role menuitemradio.
  • Pressing Enter on MenuButton opens its menu (or submenu) and places focus on its first item.
  • Pressing Space on MenuItemCheckbox changes the state without closing Menu.
  • Pressing Space on a MenuItemRadio that is not checked, without closing Menu, checks the focused MenuItemRadio and unchecks any other checked MenuItemRadio in the same group.
  • Pressing any key that corresponds to a printable character moves focus to the next MenuItem in the current Menu or MenuBar whose label begins with that printable character.

Learn more in Accessibility.

#Composition

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 and previous functions will behave. If rtl is set to true, they will be inverted. You still need to set dir="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 composite container and users will be able to navigate out of it using arrow keys.
    • If currentId is initially set to null, the 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 if orientation is horizontal or not set.
    • vertical loops only if orientation is vertical or not set.
    • If currentId is initially set to null, 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 to null, 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 of loop, 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"

    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 of wrap, 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_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 and previous functions will behave. If rtl is set to true, they will be inverted. You still need to set dir="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 composite container and users will be able to navigate out of it using arrow keys.
    • If currentId is initially set to null, the 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 if orientation is horizontal or not set.
    • vertical loops only if orientation is vertical or not set.
    • If currentId is initially set to null, 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 to null, 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 of loop, 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"

    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 of wrap, 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_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 to true when visible is updated. It'll wait for stopAnimation to be called or a CSS transition ends. If animated is set to a number, 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 a Portal by default.
  • placement "auto-start" | "auto" | "auto-end" | "top-start...

    Actual placement.

  • unstable_fixed boolean | undefined

    Whether or not the popover should have position set to fixed.

  • 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.

  • 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 to true on the parent. It will be set to false if modal is false.

  • disabled boolean | undefined

    Same as the HTML attribute.

  • focusable boolean | undefined

    When an element is disabled, it may still be focusable. It works similarly to readOnly on form elements. In this case, only aria-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 to true when visible is updated. It'll wait for stopAnimation to be called or a CSS transition ends. If animated is set to a number, 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 a Portal by default.
  • 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 to false

  • 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 composite container and users will be able to navigate out of it using arrow keys.
    • If currentId is initially set to null, the composite element itself will have focus and users will be able to navigate to it using arrow keys.
  • wrap boolean | "horizontal" | "vertical"

    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 of wrap, 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 or last.

  • groups Group[]

    Lists all the composite groups with their id and DOM ref. This state is automatically updated when registerGroup and unregisterGroup are called.

  • items Item[]

    Lists all the composite items with their id, DOM ref, disabled state and groupId if any. This state is automatically updated when registerItem and unregisterItem are called.

  • setCurrentId (value: SetStateAction<string | null | undefine...

    Sets currentId.

  • 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.

  • 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.

  • disabled boolean | undefined

    Same as the HTML attribute.

  • focusable boolean | undefined

    When an element is disabled, it may still be focusable. It works similarly to readOnly on form elements. In this case, only aria-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 composite container and users will be able to navigate out of it using arrow keys.
    • If currentId is initially set to null, the composite element itself will have focus and users will be able to navigate to it using arrow keys.
  • wrap boolean | "horizontal" | "vertical"

    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 of wrap, 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 or last.

  • groups Group[]

    Lists all the composite groups with their id and DOM ref. This state is automatically updated when registerGroup and unregisterGroup are called.

  • items Item[]

    Lists all the composite items with their id, DOM ref, disabled state and groupId if any. This state is automatically updated when registerItem and unregisterItem are called.

  • setCurrentId (value: SetStateAction<string | null | undefine...

    Sets currentId.

  • 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.

  • disabled boolean | undefined

    Same as the HTML attribute.

  • focusable boolean | undefined

    When an element is disabled, it may still be focusable. It works similarly to readOnly on form elements. In this case, only aria-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 composite container and users will be able to navigate out of it using arrow keys.
    • If currentId is initially set to null, the composite element itself will have focus and users will be able to navigate to it using arrow keys.
  • hide () => void

    Changes the visible state to false

  • unstable_moves number

    Stores the number of moves that have been performed by calling move, next, previous, up, down, first or last.

  • 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 to true

  • first () => void

    Moves focus to the first item.

  • last () => void

    Moves focus to the last item.

  • disabled boolean | undefined

    Same as the HTML attribute.

  • focusable boolean | undefined

    When an element is disabled, it may still be focusable. It works similarly to readOnly on form elements. In this case, only aria-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 composite container and users will be able to navigate out of it using arrow keys.
    • If currentId is initially set to null, the composite element itself will have focus and users will be able to navigate to it using arrow keys.
  • hide () => void

    Changes the visible state to false

  • unstable_moves number

    Stores the number of moves that have been performed by calling move, next, previous, up, down, first or last.

  • 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 to true

  • first () => void

    Moves focus to the first item.

  • last () => void

    Moves focus to the last item.

No props to show

  • disabled boolean | undefined

    Same as the HTML attribute.

  • focusable boolean | undefined

    When an element is disabled, it may still be focusable. It works similarly to readOnly on form elements. In this case, only aria-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 or last.

  • currentId string | null | undefined

    The current focused item id.

    • undefined will automatically focus the first enabled composite item.
    • null will focus the composite container and users will be able to navigate out of it using arrow keys.
    • If currentId is initially set to null, the 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, DOM ref, disabled state and groupId if any. This state is automatically updated when registerItem and unregisterItem are called.

  • setCurrentId (value: SetStateAction<string | null | undefine...

    Sets currentId.

  • 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 to false

  • move (id: string | null) => void

    Moves focus to a given item ID.

  • disabled boolean | undefined

    Same as the HTML attribute.

  • focusable boolean | undefined

    When an element is disabled, it may still be focusable. It works similarly to readOnly on form elements. In this case, only aria-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 or last.

  • currentId string | null | undefined

    The current focused item id.

    • undefined will automatically focus the first enabled composite item.
    • null will focus the composite container and users will be able to navigate out of it using arrow keys.
    • If currentId is initially set to null, the 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, DOM ref, disabled state and groupId if any. This state is automatically updated when registerItem and unregisterItem are called.

  • setCurrentId (value: SetStateAction<string | null | undefine...

    Sets currentId.

  • 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 to false

  • 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.

  • disabled boolean | undefined

    Same as the HTML attribute.

  • focusable boolean | undefined

    When an element is disabled, it may still be focusable. It works similarly to readOnly on form elements. In this case, only aria-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 or last.

  • currentId string | null | undefined

    The current focused item id.

    • undefined will automatically focus the first enabled composite item.
    • null will focus the composite container and users will be able to navigate out of it using arrow keys.
    • If currentId is initially set to null, the 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, DOM ref, disabled state and groupId if any. This state is automatically updated when registerItem and unregisterItem are called.

  • setCurrentId (value: SetStateAction<string | null | undefine...

    Sets currentId.

  • 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 to false

  • 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.

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.