Menu

A list of actions in a dropdown, enhanced with keyboard navigation.

Installation

pnpm dlx shadcn@latest add @lumi-ui/menu

Basic Usage

import {
  Menu, MenuGroup, MenuGroupLabel, MenuItem, MenuPopup, MenuSeparator, MenuTrigger
} from "@/components/ui/menu"

Recipes

Matching the Trigger Width

By default, the MenuPopup's width automatically adapts to fit the widest menu item inside it. This provides great flexibility.

However, for components like theme switchers or custom select inputs, you often want the menu to have the exact same width as its trigger to create a more seamless and polished look. For these scenarios, use the matchAnchorWidth prop on the MenuPopup component.

Open on hover

To create a menu that opens on hover, add the openOnHover prop to Menu. You can additionally configure how quickly the menu opens on hover using the delay prop.

Checkbox items

Use the <MenuCheckboxItem> part to create a menu item that can toggle a setting on or off.

Radio items

Use the <MenuRadioGroup> and <MenuRadioItem> parts to create menu items that work like radio buttons.

Close on click

Use the closeOnClick prop to change whether the menu closes when an item is clicked.

Group labels

Use the <MenuGroupLabel> part to add a label to a <MenuGroup>

Nested menu

To create a submenu, nest another menu inside the parent menu with <MenuSubMenu>. Use the <MenuSubmenuTrigger> part for the menu item that opens the nested menu.

Use the render prop to compose a menu item with an anchor element.

Open a dialog

In order to open a dialog using a menu, control the dialog state and open it imperatively using the onClick handler on the menu item.

Anatomy

<Menu>
  <MenuTrigger />
  <MenuPopup>
    <MenuItem />
    <MenuItem>
      <MenuShortcut />
    </MenuItem>
    <MenuCheckboxItem />
    <MenuSeparator />
    <MenuGroup>
      <MenuGroupLabel />
    </MenuGroup>
    <MenuRadioGroup>
      <MenuRadioItem />
    </MenuRadioGroup>
    <MenuSubMenu>
      <MenuSubMenuTrigger />
      <MenuSubMenuPopup />
    </MenuSubMenu>
  </MenuPopup>
</Menu>
ComponentRole
MenuThe root component and context provider. It wraps the entire menu functionality but does not render a visible element itself.
MenuTriggerThe button or element that the user interacts with to open or close the menu. It's best used with the render prop to pass functionality to your own Button.
MenuPopupComponent that wraps the floating panel containing your menu items. It handles portaling, positioning, and animations.
MenuItemThe most common interactive element within a menu. Can contain text, icons, and a MenuShortcut. Use the variant="destructive" prop for dangerous actions.
MenuCheckboxItemA menu item that functions as a toggle. It displays a checkmark when active. Use the checked and onCheckedChange props to control its state.
MenuRadioGroupWraps a set of MenuRadioItem components to create a group where only one item can be selected. Manages the group's state via the value and onValueChange props.
MenuRadioItemA menu item within a MenuRadioGroup that represents a single choice. It displays an indicator when selected.
MenuGroupA simple wrapper used to group related menu items, often used in conjunction with a MenuGroupLabel.
MenuGroupLabelA non-interactive, styled label used to provide a title for a MenuGroup. This is great for organizing complex menus.
MenuSubMenuThe root component for a nested menu. It wraps the trigger and the content of the submenu.
MenuSubMenuTriggerThe specific MenuItem that, when hovered or clicked, will open its corresponding MenuSubMenuPopup. It automatically includes a right-facing chevron.
MenuSubMenuPopupThe floating panel that contains the items for a nested submenu. It has its own positioning relative to the MenuSubMenuTrigger.
MenuShortcutA simple <span> styled to be right-aligned with muted text, perfect for displaying keyboard shortcuts like ⌘S. It should be placed inside a MenuItem.

Migration from shadcn/ui

The component has been renamed from DropdownMenu to Menu for brevity and clarity. The names for content panels and labels have also been updated.

shadcn/uilumi/uiChange
DropdownMenuMenuRenamed
DropdownMenuContentMenuPopupRenamed
DropdownMenuLabelMenuGroupLabelRenamed
DropdownMenuSubMenuSubMenuRenamed
DropdownMenuSubContentMenuSubMenuPopupRenamed
(All other parts)(e.g., MenuItem)Renamed

Key Differences & New Features

Menu component introduces several enhancements for better positioning and styling, which are exposed as props on the MenuPopup component.

Featurelumi/uishadcn/ui
Popup ArrowshowArrow prop on MenuPopupNot available
Width MatchingmatchAnchorWidth prop on MenuPopupNot available
PositioningExplicit side, align, sideOffset propsImplicitly controlled via props on DropdownMenuContent

Migration Example

dropdown-menu-demo.tsx
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuPortal,
  DropdownMenuSeparator,
  DropdownMenuSub,
  DropdownMenuSubContent,
  DropdownMenuSubTrigger,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
 
function Demo() {
  return (
    <DropdownMenu>
      <DropdownMenuTrigger>Open Menu</DropdownMenuTrigger>
      <DropdownMenuContent>
        <DropdownMenuItem>Profile</DropdownMenuItem>
        <DropdownMenuItem>Settings</DropdownMenuItem>
        <DropdownMenuSeparator />
        <DropdownMenuSub>
          <DropdownMenuSubTrigger>More Actions</DropdownMenuSubTrigger>
          <DropdownMenuPortal>
            <DropdownMenuSubContent>
              <DropdownMenuItem>Delete</DropdownMenuItem>
            </DropdownMenuSubContent>
          </DropdownMenuPortal>
        </DropdownMenuSub>
      </DropdownMenuContent>
    </DropdownMenu>
  );
}