Dropdown Menu
A menu of actions or options triggered by a button.
CMS Demo
See how content editors configure dropdown menus in a CMS:
Basic Usage
Installation
pnpm add @corew500/uiUsage
import {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuItem,
} from "@mordecai-design-system/ui"<DropdownMenu>
<DropdownMenuTrigger>Open</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuItem>Edit</DropdownMenuItem>
<DropdownMenuItem>Delete</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>Examples
With Groups
<DropdownMenuContent>
<DropdownMenuGroup>
<DropdownMenuLabel>My Account</DropdownMenuLabel>
<DropdownMenuItem>Profile</DropdownMenuItem>
<DropdownMenuItem>Settings</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuItem>Logout</DropdownMenuItem>
</DropdownMenuContent>With Submenus
<DropdownMenuContent>
<DropdownMenuItem>New File</DropdownMenuItem>
<DropdownMenuSub>
<DropdownMenuSubTrigger>Share</DropdownMenuSubTrigger>
<DropdownMenuSubContent>
<DropdownMenuItem>Email</DropdownMenuItem>
<DropdownMenuItem>Slack</DropdownMenuItem>
</DropdownMenuSubContent>
</DropdownMenuSub>
</DropdownMenuContent>With Checkboxes
const [showPanel, setShowPanel] = useState(true)
<DropdownMenuCheckboxItem
checked={showPanel}
onCheckedChange={setShowPanel}
>
Show Panel
</DropdownMenuCheckboxItem>With Radio Items
const [position, setPosition] = useState("bottom")
<DropdownMenuRadioGroup value={position} onValueChange={setPosition}>
<DropdownMenuRadioItem value="top">Top</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="bottom">Bottom</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>Destructive Items
<DropdownMenuItem variant="destructive">
Delete
</DropdownMenuItem>With Shortcuts
<DropdownMenuItem>
New Tab
<DropdownMenuShortcut>⌘T</DropdownMenuShortcut>
</DropdownMenuItem>Sub-components
| Component | Description |
|-----------|-------------|
| DropdownMenu | Root component |
| DropdownMenuTrigger | Button that opens the menu |
| DropdownMenuContent | The popup content |
| DropdownMenuItem | Clickable menu item |
| DropdownMenuCheckboxItem | Checkable menu item |
| DropdownMenuRadioGroup | Group of radio items |
| DropdownMenuRadioItem | Selectable radio item |
| DropdownMenuLabel | Non-interactive label |
| DropdownMenuSeparator | Visual divider |
| DropdownMenuShortcut | Keyboard shortcut hint |
| DropdownMenuGroup | Grouping container |
| DropdownMenuSub | Submenu container |
| DropdownMenuSubTrigger | Submenu trigger |
| DropdownMenuSubContent | Submenu content |
Props
DropdownMenuItem
| Prop | Type | Default | Description |
|---|---|---|---|
| onClick | MouseEventHandler<HTMLElement> | — | The click handler for the menu item. |
| disabled | enum | false | Whether the component should ignore user interaction. |
| label | string | — | Overrides the text label to use when the item is matched during keyboard text navigation. |
| id | string | — | @ignore |
| closeOnClick | enum | true | Whether to close the menu when the item is clicked. |
| nativeButton | enum | true | Whether the component renders a native `<button>` element when replacing it via the `render` prop. Set to `false` if the rendered element is not a button (e.g. `<div>`). |
| style | enum | — | Style applied to the element, or a function that returns a style object based on the component’s state. |
| className | enum | — | CSS class applied to the element, or a function that returns a class based on the component’s state. |
| render | enum | — | Allows you to replace the component’s HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render. |
| inset | enum | — | — |
| variant | enum | default | — |
DropdownMenuContent
| Prop | Type | Default | Description |
|---|---|---|---|
| id | string | — | @ignore |
| finalFocus | enum | — | Determines the element to focus when the menu is closed. - `false`: Do not move focus. - `true`: Move focus based on the default behavior (trigger or previously focused element). - `RefObject`: Move focus to the ref element. - `function`: Called with the interaction type (`mouse`, `touch`, `pen`, or `keyboard`). Return an element to focus, `true` to use the default behavior, or `false`/`undefined` to do nothing. |
| style | enum | — | Style applied to the element, or a function that returns a style object based on the component’s state. |
| className | enum | — | CSS class applied to the element, or a function that returns a class based on the component’s state. |
| render | enum | — | Allows you to replace the component’s HTML element with a different tag, or compose it with another component. Accepts a `ReactElement` or a function that returns the element to render. |
| align | enum | start | How to align the popup relative to the specified side. |
| alignOffset | enum | 0 | Additional offset along the alignment axis in pixels. Also accepts a function that returns the offset to read the dimensions of the anchor and positioner elements, along with its side and alignment. The function takes a `data` object parameter with the following properties: - `data.anchor`: the dimensions of the anchor element with properties `width` and `height`. - `data.positioner`: the dimensions of the positioner element with properties `width` and `height`. - `data.side`: which side of the anchor element the positioner is aligned against. - `data.align`: how the positioner is aligned relative to the specified side. @example ```jsx <Positioner alignOffset={({ side, align, anchor, positioner }) => { return side === 'top' || side === 'bottom' ? anchor.width : anchor.height; }} /> ``` |
| side | enum | bottom | Which side of the anchor element to align the popup against. May automatically change to avoid collisions. |
| sideOffset | enum | 4 | Distance between the anchor and the popup in pixels. Also accepts a function that returns the distance to read the dimensions of the anchor and positioner elements, along with its side and alignment. The function takes a `data` object parameter with the following properties: - `data.anchor`: the dimensions of the anchor element with properties `width` and `height`. - `data.positioner`: the dimensions of the positioner element with properties `width` and `height`. - `data.side`: which side of the anchor element the positioner is aligned against. - `data.align`: how the positioner is aligned relative to the specified side. @example ```jsx <Positioner sideOffset={({ side, align, anchor, positioner }) => { return side === 'top' || side === 'bottom' ? anchor.height : anchor.width; }} /> ``` |
Keyboard Navigation
| Key | Action |
|-----|--------|
| ↑ ↓ | Navigate items |
| Enter Space | Select item |
| → | Open submenu |
| ← | Close submenu |
| Esc | Close menu |