---
title: Dropdown Menu
description: Displays a menu to the user — such as a set of actions or functions — triggered by a button, built on the Base UI Menu primitive.
---

```tsx
"use client";

import { Button } from "@/registry/base/ui/button";
import {
  DropdownMenu,
  DropdownMenuCheckboxItem,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuRadioGroup,
  DropdownMenuRadioItem,
  DropdownMenuSeparator,
  DropdownMenuShortcut,
  DropdownMenuSub,
  DropdownMenuSubContent,
  DropdownMenuSubTrigger,
  DropdownMenuTrigger,
} from "@/registry/base/ui/dropdown-menu";

export default function DropdownMenuDemo() {
  return (
    <DropdownMenu>
      <DropdownMenuTrigger render={<Button variant="outline">Open menu</Button>} />
      <DropdownMenuContent align="start" className="w-56">
        <DropdownMenuGroup>
          <DropdownMenuLabel>My Account</DropdownMenuLabel>
          <DropdownMenuItem>
            Profile
            <DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut>
          </DropdownMenuItem>
          <DropdownMenuItem>
            Billing
            <DropdownMenuShortcut>⌘B</DropdownMenuShortcut>
          </DropdownMenuItem>
          <DropdownMenuItem>
            Settings
            <DropdownMenuShortcut>⌘S</DropdownMenuShortcut>
          </DropdownMenuItem>
        </DropdownMenuGroup>
        <DropdownMenuSeparator />
        <DropdownMenuSub>
          <DropdownMenuSubTrigger>Invite users</DropdownMenuSubTrigger>
          <DropdownMenuSubContent>
            <DropdownMenuItem>Email</DropdownMenuItem>
            <DropdownMenuItem>Message</DropdownMenuItem>
          </DropdownMenuSubContent>
        </DropdownMenuSub>
        <DropdownMenuSeparator />
        <DropdownMenuCheckboxItem defaultChecked>
          Status bar
        </DropdownMenuCheckboxItem>
        <DropdownMenuCheckboxItem>Activity bar</DropdownMenuCheckboxItem>
        <DropdownMenuSeparator />
        <DropdownMenuRadioGroup defaultValue="bottom">
          <DropdownMenuLabel>Panel position</DropdownMenuLabel>
          <DropdownMenuRadioItem value="top">Top</DropdownMenuRadioItem>
          <DropdownMenuRadioItem value="bottom">Bottom</DropdownMenuRadioItem>
          <DropdownMenuRadioItem value="right">Right</DropdownMenuRadioItem>
        </DropdownMenuRadioGroup>
        <DropdownMenuSeparator />
        <DropdownMenuItem variant="destructive">Log out</DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenu>
  );
}
```

## Installation

<InstallCommand item="dropdown-menu" />

## Usage

```tsx
"use client";

import { Button } from "@/components/ui/button";
import {
  DropdownMenu,
  DropdownMenuCheckboxItem,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuRadioGroup,
  DropdownMenuRadioItem,
  DropdownMenuSeparator,
  DropdownMenuShortcut,
  DropdownMenuSub,
  DropdownMenuSubContent,
  DropdownMenuSubTrigger,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";

export default function DropdownMenuDemo() {
  return (
    <DropdownMenu>
      <DropdownMenuTrigger render={<Button variant="outline">Open menu</Button>} />
      <DropdownMenuContent align="start" className="w-56">
        <DropdownMenuGroup>
          <DropdownMenuLabel>My Account</DropdownMenuLabel>
          <DropdownMenuItem>
            Profile
            <DropdownMenuShortcut>⇧⌘P</DropdownMenuShortcut>
          </DropdownMenuItem>
          <DropdownMenuItem>
            Billing
            <DropdownMenuShortcut>⌘B</DropdownMenuShortcut>
          </DropdownMenuItem>
          <DropdownMenuItem>
            Settings
            <DropdownMenuShortcut>⌘S</DropdownMenuShortcut>
          </DropdownMenuItem>
        </DropdownMenuGroup>
        <DropdownMenuSeparator />
        <DropdownMenuSub>
          <DropdownMenuSubTrigger>Invite users</DropdownMenuSubTrigger>
          <DropdownMenuSubContent>
            <DropdownMenuItem>Email</DropdownMenuItem>
            <DropdownMenuItem>Message</DropdownMenuItem>
          </DropdownMenuSubContent>
        </DropdownMenuSub>
        <DropdownMenuSeparator />
        <DropdownMenuCheckboxItem defaultChecked>
          Status bar
        </DropdownMenuCheckboxItem>
        <DropdownMenuCheckboxItem>Activity bar</DropdownMenuCheckboxItem>
        <DropdownMenuSeparator />
        <DropdownMenuRadioGroup defaultValue="bottom">
          <DropdownMenuLabel>Panel position</DropdownMenuLabel>
          <DropdownMenuRadioItem value="top">Top</DropdownMenuRadioItem>
          <DropdownMenuRadioItem value="bottom">Bottom</DropdownMenuRadioItem>
          <DropdownMenuRadioItem value="right">Right</DropdownMenuRadioItem>
        </DropdownMenuRadioGroup>
        <DropdownMenuSeparator />
        <DropdownMenuItem variant="destructive">Log out</DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenu>
  );
}
```

## API reference

### DropdownMenu

Extends the [Base UI Menu](https://base-ui.com/react/components/menu)
Root — all its props apply.

| Prop                   | Type                                          | Default |
| ---------------------- | --------------------------------------------- | ------- |
| `open` / `defaultOpen` | `boolean`                                     | `false` |
| `onOpenChange`         | `(open: boolean) => void`                     | —       |
| `modal`                | `boolean`                                     | `true`  |
| `loopFocus`            | `boolean` — arrow keys wrap (not `loop`)      | `true`  |
| `closeParentOnEsc`     | `boolean` — Esc in a submenu closes the parent | —      |

### DropdownMenuTrigger

The only part rendering a native `<button>`; accepts the `render` prop.
Hover-opening lives here (and on `DropdownMenuSubTrigger`), not the
Root.

| Prop          | Type      | Default    |
| ------------- | --------- | ---------- |
| `openOnHover` | `boolean` | `false`    |
| `delay`       | `number`  | `100` (ms) |

### DropdownMenuItem, DropdownMenuCheckboxItem, DropdownMenuRadioItem

All render `<div>` elements — disabled styling comes from the
`data-disabled` attribute, not the `disabled` HTML attribute.
`closeOnClick` defaults differ: `true` on `Item`, `false` on
`CheckboxItem`/`RadioItem`, so toggling options keeps the menu open.

| Prop                         | Type                             | Default     |
| ---------------------------- | -------------------------------- | ----------- |
| `variant` (Item)             | `"default" \| "destructive"`     | `"default"` |
| `inset`                      | `boolean` — align with checkables | `false`    |
| `checked` / `onCheckedChange` (CheckboxItem) | `boolean` / callback | —          |
| `value` (RadioItem)          | `string` (required)              | —           |

### DropdownMenuLabel, DropdownMenuGroup, DropdownMenuRadioGroup

`DropdownMenuLabel` must be placed inside `DropdownMenuGroup` or
`DropdownMenuRadioGroup` — Base UI wires the group's `aria-labelledby`
to it and throws otherwise. `DropdownMenuRadioGroup` takes
`value`/`onValueChange`.

### DropdownMenuSub, DropdownMenuSubTrigger, DropdownMenuSubContent

Submenus wrap `SubmenuRoot` (not a nested root). Positioning is
automatic and RTL-aware — it defaults to `side="inline-end"
align="start"`; don't override with a hardcoded `side="right"`.

### DropdownMenuContent, DropdownMenuSeparator, DropdownMenuShortcut, DropdownMenuPortal

Styled parts; the shortcut is a plain `span` for trailing hints.
