Skip to main content

Menu

Menu is a dropdown menu component with keyboard navigation and click-outside closing.

Open in Storybook

Import​

import { Menu, MenuButton, MenuList, MenuItem } from "@tosui/react";

Basic usage​

Button variants​

MenuButton accepts all Button props.

Disabled items​

Controlled state​

Pass isOpen when application state owns the open state. Update that state from onOpen and onClose.

function ControlledMenu() {
const [isOpen, setIsOpen] = useState(false);

return (
<Menu
isOpen={isOpen}
onOpen={() => setIsOpen(true)}
onClose={() => setIsOpen(false)}
>
<MenuButton>Controlled Menu</MenuButton>
<MenuList>
<MenuItem>Option 1</MenuItem>
<MenuItem>Option 2</MenuItem>
</MenuList>
</Menu>
);
}

Common patterns​

User account Menu​

<Menu>
<MenuButton variant="ghost">
<Avatar size="sm" name="John Doe" />
</MenuButton>
<MenuList>
<MenuItem onClick={() => navigate("/profile")}>Profile</MenuItem>
<MenuItem onClick={() => navigate("/settings")}>Settings</MenuItem>
<MenuItem onClick={() => logout()}>Sign Out</MenuItem>
</MenuList>
</Menu>

Actions menu​

<Menu>
<MenuButton size="sm" variant="ghost">
<MoreIcon />
</MenuButton>
<MenuList>
<MenuItem onClick={handleEdit}>Edit</MenuItem>
<MenuItem onClick={handleDuplicate}>Duplicate</MenuItem>
<MenuItem onClick={handleArchive}>Archive</MenuItem>
<MenuItem onClick={handleDelete}>Delete</MenuItem>
</MenuList>
</Menu>

Behavior​

  • Click outside closes the menu
  • Escape key closes the menu
  • Clicking a MenuItem closes the menu
  • Menu opens below the button by default

Props reference​

PropTypeDefaultDescription
isOpenboolean-Controlled open state
onOpen() => void-Called when menu opens
onClose() => void-Called when menu closes
classNamestring-Additional CSS class
childrenReactNode-Menu subcomponents

MenuButton accepts all Button props.

PropTypeDefaultDescription
classNamestring-Additional CSS class
childrenReactNode-Menu items
PropTypeDefaultDescription
onClick() => void-Click handler
disabledbooleanfalseDisable the item
classNamestring-Additional CSS class
childrenReactNode-Item content

Accessibility​

  • MenuButton uses aria-haspopup="menu" and aria-expanded.
  • MenuList uses role="menu" and focuses its first enabled item when it opens.
  • MenuItem uses role="menuitem".
  • Up Arrow and Down Arrow move focus between enabled items.
  • Escape closes the menu and returns focus to MenuButton.
  • Tab closes the menu and moves focus beyond the trigger.

TypeScript​

import { Menu, MenuButton, MenuList, MenuItem, type MenuProps, type MenuButtonProps, type MenuListProps, type MenuItemProps } from "@tosui/react";