Dropdown Menu

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

Installation

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

Basic Usage

Recipes

Matching the Trigger Width

By default, the DropdownMenuContent'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 DropdownMenuContent component.

Open on hover

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

Checkbox items

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

Radio items

Use the <DropdownMenuRadioGroup> and <DropdownMenuRadioItem> 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 <DropdownMenuGroupLabel> part to add a label to a <DropdownMenuGroup>

Nested menu

To create a submenu, nest another menu inside the parent menu with <DropdownMenuSubMenu>. Use the <DropdownMenuSubmenuTrigger> 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.

Create your own

Anatomy

For the vast majority of use cases, these are the only components you will need. They provide the best developer experience out of the box.

<DropdownMenu>
  <DropdownMenuTrigger />
  <DropdownMenuContent>
    <DropdownMenuItem />
    <DropdownMenuItem>
      <DropdownMenuShortcut />
    </DropdownMenuItem>
    <DropdownMenuCheckboxItem />
    <DropdownMenuSeparator />
    <DropdownMenuGroup>
      <DropdownMenuGroupLabel />
    </DropdownMenuGroup>
    <DropdownMenuRadioGroup>
      <DropdownMenuRadioItem />
    </DropdownMenuRadioGroup>
    <DropdownMenuSubMenu>
      <DropdownMenuSubMenuTrigger />
      <DropdownMenuSubMenuContent>
        {/* Submenu items  */}
      </DropdownMenuSubMenuContent>
    </DropdownMenuSubMenu>
  </DropdownMenuContent>
</DropdownMenu>
ComponentRole
DropdownMenuThe root component and context provider. It wraps the entire menu functionality but does not render a visible element itself.
DropdownMenuTriggerThe button that the user interacts with to open or close the menu. Use render prop to pass functionality to your own Button.
DropdownMenuContentComponent that wraps the floating panel containing your menu items. It handles portaling, positioning, and animations.
DropdownMenuItemThe most common interactive element within a menu. Can contain text, icons, and a DropdownMenuShortcut. Use the variant="destructive" prop for dangerous actions.
DropdownMenuCheckboxItemA menu item that functions as a toggle. It displays a checkmark when active. Use the checked and onCheckedChange props to control its state.
DropdownMenuRadioGroupWraps a set of DropdownMenuRadioItem components to create a group where only one item can be selected. Manages the group's state via the value and onValueChange props.
DropdownMenuRadioItemA menu item within a MenuRadioGroup that represents a single choice. It displays an indicator when selected.
DropdownMenuGroupA simple wrapper used to group related menu items, often used in conjunction with a DropdownMenuGroupLabel.
DropdownMenuGroupLabelA non-interactive, styled label used to provide a title for a DropdownMenuGroup. Must use within DropdownMenuGroup.
DropdownMenuSubMenuThe root component for a nested menu.
DropdownMenuSubMenuTriggerThe specific MenuItem that, when hovered or clicked, will open its corresponding DropdownMenuSubMenuPopup. It automatically includes a right-facing chevron.
DropdownMenuSubMenuPopupThe floating panel that contains the items for a nested submenu.
DropdownMenuShortcutA 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

shadcn/uilumi/uiChange
DropdownMenuSubDropdownMenuSubMenuRenamed for explicitness.
DropdownMenuSubTriggerDropdownMenuSubMenuTriggerRenamed to align with DropdownMenuSubMenu.
DropdownMenuSubContentDropdownMenuSubMenuContentRenamed to align with DropdownMenuSubMenu.
DropdownMenuLabelDropdownMenuGroupLabelRenamed and now has a required parent component.

Structural Changes

DropdownMenuGroupLabel must be a direct child of DropdownMenuGroup. This enforces a more organized and accessible menu structure.

shadcn/uilumi/uiChange
DropdownMenuLabel could be a direct child of DropdownMenuContent.DropdownMenuGroupLabel must be nested inside DropdownMenuGroup.Stricter, more semantic grouping.
  • shadcn/ui:
<DropdownMenuContent>
  <DropdownMenuLabel>Section Title</DropdownMenuLabel>
  <DropdownMenuItem>Item 1</DropdownMenuItem>
</DropdownMenuContent>
  • lumi/ui:
<DropdownMenuContent>
  <DropdownMenuGroup>
    <DropdownMenuGroupLabel>Section Title</DropdownMenuGroupLabel>
    <DropdownMenuItem>Item 1</DropdownMenuItem>
  </DropdownMenuGroup>
</DropdownMenuContent>

Prop and Feature Changes

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

Featurelumi/uishadcn/ui
Positioning PropsDropdownMenuContent includes side, sideOffset, align, and alignOffset directly.These props are inherited from the underlying Radix UI component but not explicitly defined.
Arrow DisplayDropdownMenuContent has a showArrow prop to display a pointer arrow.No built-in arrow functionality.
Width MatchingDropdownMenuContent has a matchAnchorWidth prop to match the trigger's width.This behavior requires manual implementation.
AnimationAnimations are handled via data-[starting-style] and data-[ending-style] attributes for more direct CSS control.Animations are handled via data-[state=open] and data-[state=closed] with Tailwind CSS animation classes.

Migration Example

dropdown-menu-demo.tsx
import { Button } from "@/components/ui/button"
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuPortal,
  DropdownMenuSeparator,
  DropdownMenuShortcut,
  DropdownMenuSub,
  DropdownMenuSubContent,
  DropdownMenuSubTrigger,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
 
export function DropdownMenuDemo() {
  return (
    <DropdownMenu>
      <DropdownMenuTrigger asChild>
        <Button variant="outline">Open</Button>
      </DropdownMenuTrigger>
      <DropdownMenuContent className="w-56" align="start">
        <DropdownMenuLabel>My Account</DropdownMenuLabel>
        <DropdownMenuGroup>
          <DropdownMenuItem>
            Profile
            <DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut>
          </DropdownMenuItem>
          <DropdownMenuItem>
            Billing
            <DropdownMenuShortcut>⌘B</DropdownMenuShortcut>
          </DropdownMenuItem>
          <DropdownMenuItem>
            Settings
            <DropdownMenuShortcut>⌘S</DropdownMenuShortcut>
          </DropdownMenuItem>
          <DropdownMenuItem>
            Keyboard shortcuts
            <DropdownMenuShortcut>⌘K</DropdownMenuShortcut>
          </DropdownMenuItem>
        </DropdownMenuGroup>
        <DropdownMenuSeparator />
        <DropdownMenuGroup>
          <DropdownMenuItem>Team</DropdownMenuItem>
          <DropdownMenuSub>
            <DropdownMenuSubTrigger>Invite users</DropdownMenuSubTrigger>
            <DropdownMenuPortal>
              <DropdownMenuSubContent>
                <DropdownMenuItem>Email</DropdownMenuItem>
                <DropdownMenuItem>Message</DropdownMenuItem>
                <DropdownMenuSeparator />
                <DropdownMenuItem>More...</DropdownMenuItem>
              </DropdownMenuSubContent>
            </DropdownMenuPortal>
          </DropdownMenuSub>
          <DropdownMenuItem>
            New Team
            <DropdownMenuShortcut>⌘+T</DropdownMenuShortcut>
          </DropdownMenuItem>
        </DropdownMenuGroup>
        <DropdownMenuSeparator />
        <DropdownMenuItem>GitHub</DropdownMenuItem>
        <DropdownMenuItem>Support</DropdownMenuItem>
        <DropdownMenuItem disabled>API</DropdownMenuItem>
        <DropdownMenuSeparator />
        <DropdownMenuItem>
          Log out
          <DropdownMenuShortcut>⇧⌘Q</DropdownMenuShortcut>
        </DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenu>
  )
}