Dropdown Menu
A list of actions behind a button. Use it for row and page actions, bulk actions on a narrow toolbar, filters, and account menus. Arrow keys move through items, and focus returns to the trigger when it closes.
Usage
import { Button } from "@tulipfarm/sprout/button";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@tulipfarm/sprout/dropdown-menu";
<DropdownMenu>
<DropdownMenuTrigger
render={<Button variant="ghost" size="icon-sm" aria-label="Actions for row 1042" />}
>
<MoreH size={16} aria-hidden="true" />
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuGroup>
<DropdownMenuItem onClick={edit}>Edit row</DropdownMenuItem>
<DropdownMenuItem onClick={history}>History</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuItem variant="destructive" onClick={remove}>
Delete row
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>Pass a Button to DropdownMenuTrigger through render. Icon-only triggers need an aria-label. Disable the trigger with disabled on either part, and set aria-busy while work runs.
Sizes
DropdownMenuContent size is "anchor" (the default: as wide as the trigger, at least 8rem) or "menu" (a fixed 16rem). Use anchor for text triggers like “Selected actions” and short row menus. Use menu for icon triggers with icon items, longer labels, and two-line choices. Both stay inside the viewport and scroll when tall.
Row and page actions
A More button opens actions for one row or page. Icon triggers align the menu to their end.
Placement
Set side, align, sideOffset, and alignOffset. Menus open below and start-aligned by default. Composers and footers use side="top". The menu flips when there is no room.
Chat
The composer opens upward with two-line choices. The header menu disables actions while a reply is sending.
States
A busy trigger changes its label and sets aria-busy. Items take disabled; they stay readable at half opacity and can’t be chosen. When work finishes, show the result next to the trigger and offer only the actions that still apply.
Selection actions
Narrow toolbars fold bulk actions into one menu. The trigger shows progress and turns busy while work runs.
Checkboxes and radios
DropdownMenuCheckboxItem and DropdownMenuRadioItem show a check on the right. They keep the menu open so people can change several options; filters also pass closeOnClick={false} to say so outright. Pass closeOnClick to close after one choice.
Checkbox menus
Filters and column pickers keep the menu open with closeOnClick={false}. The last visible column can’t be hidden.
Links and submenus
Render an item as a link with render={<a href="…" />} or your router’s link. DropdownMenuSub nests a menu: the DropdownMenuSubTrigger adds a chevron and opens DropdownMenuSubContent to the side. Long names truncate inside the 16rem menu.
Sidebar menus
The workspace menu opens below with a switcher submenu. The account menu opens upward with a theme submenu. Items are links.
Controlled
Control the menu with open and onOpenChange to open it from a shortcut. finalFocus on the content decides where focus lands when it closes.
Controlled
Focus the card and press Shift + F10 or the Menu key. The menu opens through open and onOpenChange, then finalFocus returns to the card.
Favorite: off · View: List
No action selected.
Menubar
import { Menubar } from "@base-ui/react/menubar";
<Menubar>
<DropdownMenu>
<DropdownMenuTrigger className="menubar-trigger">File</DropdownMenuTrigger>
<DropdownMenuContent alignOffset={-4} sideOffset={8} className="min-w-48">
<DropdownMenuItem>New task<DropdownMenuShortcut>⌘ N</DropdownMenuShortcut></DropdownMenuItem>
<DropdownMenuItem inset>Duplicate</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</Menubar>Menubar
Each menu is a DropdownMenu inside Base UI’s Menubar. Arrow keys move between menus; inset aligns text with icon rows.
Layout: Board
Accessibility
The trigger has aria-haspopup="menu" and aria-expanded. Enter, Space, and Arrow Down open the menu. Arrow keys move, typing jumps to a matching item, Arrow Right opens a submenu and Arrow Left closes it, and Escape closes the menu and returns focus. Disabled items can still be reached with arrow keys so people know they exist, but they can’t be chosen.
Menus fade and scale in from the trigger over 120ms. Motion turns off when reduced motion is requested. In forced-colors mode the highlighted item gets an outline.
Theme tokens
Menus use --sprout-surface, --sprout-line, --sprout-hover, --sprout-text, --sprout-muted, --sprout-danger, --sprout-danger-subtle, --sprout-shadow-overlay, and the panel and control radii. They need no brand color, so they look the same with the neutral and TulipFarm themes in light and dark mode.