What is Dropdown menu?

Dropdown menu: A dropdown menu is a list of actions or options that opens below a button, where arrow keys move through the items and Enter runs the chosen one.

A dropdown menu opens from a trigger button and lists things the user can do: open a profile, change a setting, duplicate or delete an item, switch workspace. Items can carry icons and keyboard shortcut hints, can be grouped with separators, can be checkable, and can open submenus. The pattern comes from desktop application menus, and it carries their keyboard behavior with it, which is what makes a menu different from a popover holding a few buttons.

When to use it

  • Secondary actions on an item, such as the three-dot menu on a table row or a card.
  • Account and workspace menus in the top bar.
  • Choosing a view or a sort order, using radio items so the current choice is marked.
  • Not for choosing a value in a form, which is a select or a combobox, and not for site navigation, which is a nav landmark with a list of links. Menu roles tell screen readers to expect application behavior.

Accessibility

The WAI-ARIA menu button pattern defines it. The trigger has aria-haspopup="menu" and aria-expanded. The popup has role="menu", and each item is role="menuitem", menuitemcheckbox or menuitemradio, with aria-checked on the last two. Unlike a combobox, focus moves into the menu when it opens.

  • Enter, Space or Down Arrow opens the menu and focuses the first item; Up Arrow opens it and focuses the last.
  • Up and Down move between items and wrap at the ends; Home and End jump to the first and last item.
  • Typing a letter moves to the next item starting with it.
  • Right Arrow opens a submenu, Left Arrow closes it.
  • Enter activates an item and closes the menu; Escape closes without acting; both return focus to the trigger.
  • Disabled items stay in the DOM with aria-disabled so users can still find them.

How to build one in React

MiniDev's DropdownMenu is built on the Base UI menu, so the roles, focus movement and typeahead above come for free:

tsx
import { EllipsisIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"

export function RowActions({ onDuplicate, onDelete }: { onDuplicate: () => void; onDelete: () => void }) {
  return (
    <DropdownMenu>
      <DropdownMenuTrigger render={<Button variant="ghost" size="icon" aria-label="More actions" />}>
        <EllipsisIcon />
      </DropdownMenuTrigger>
      <DropdownMenuContent align="end">
        <DropdownMenuItem onClick={onDuplicate}>
          Duplicate
          <DropdownMenuShortcut>⌘D</DropdownMenuShortcut>
        </DropdownMenuItem>
        <DropdownMenuSeparator />
        <DropdownMenuItem variant="destructive" onClick={onDelete}>Delete</DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenu>
  )
}

Keep destructive items last and separated, and confirm them with an alert dialog when they cannot be undone. Show a shortcut hint only next to actions that really have one. ContextMenu is the same menu opened by right click, and Menubar groups several menus in a row. Browse the overlays category for more.

Dropdown MenuuiShadcn compatible dropdown menu on Base UI with groups, labels, checkbox and radio items, submenus, shortcuts, separators and destructive items.npx shadcn@latest add @minidev/dropdown-menuContext MenuuiRight click context menu that opens at the cursor with menu items, including destructive items in red. Closes on selection or click outside, in React.npx shadcn@latest add @minidev/context-menu