Dropdown Menu
Dropdown menus display a list of actions or selectable options that appear when a user clicks a trigger element. They are commonly used in toolbars, table rows, navigation, and anywhere you need to present a compact set of choices without taking up permanent screen space.
The React component wraps Radix UI’s Dropdown Menu primitive and accepts props for customisation — trigger, options, customContent, and callback handlers.
The Vue component uses Teleport for portal rendering and named slots (#trigger, #customContent, #item, #itemRight, #footer) for flexible composition alongside props for configuration.
Loading Code Block...Full example
Section titled “Full example”The default configuration renders a dropdown menu with a custom trigger and a set of options. Clicking the trigger toggles the menu open and closed.
Loading Code Block...Searchable
Section titled “Searchable”Enable the built-in search input to allow users to filter through options. Use
Loading Code Block...Alignment
Section titled “Alignment”Control the horizontal alignment of the dropdown relative to its trigger using the align prop. Supported values are start, center, and end.
Position
Section titled “Position”The position prop controls which side of the trigger the dropdown opens from. Supported values are top, bottom, left, and right.
Loading Code Block...Disabled
Section titled “Disabled”Set disabled to prevent the dropdown from being triggered. The trigger element receives reduced opacity and pointer-events: none.
Loading Code Block...Control the dropdown width with the width prop. Use the interactive demo below to see the difference between automatic and fixed sizing:
"content"(default): Allows the dropdown panel to naturally auto-size based on its content (longest option or trigger element).number: Forces a fixed pixel width (e.g.,300) regardless of the content size.
Offset
Section titled “Offset”Use the offset prop to adjust the gap (in pixels) between the dropdown panel and its trigger element. The default is 4.
Multiple selection
Section titled “Multiple selection”Enable multi-select mode with the multiple prop. When active, each option renders a checkbox and the menu stays open after selection. The onSelect callback returns an array of selected values.
Loading Code Block...With right content
Section titled “With right content”Render a right-aligned element on each option row — useful for keyboard shortcuts, badges, or status indicators. Each row uses justify-between for proper left/right alignment.
Set option.rightContent on any option.
You can either pass option.rightContent (a component / VNode) per option, or use the #itemRight=”{ option, isSelected }” scoped slot to render right-aligned content for every row.
Loading Code Block...Disabled options
Section titled “Disabled options”Set option.disabled: true to dim a single row and exclude it from keyboard focus and selection. Useful for context-sensitive actions that aren’t currently available.
Loading Code Block...Custom item rendering
Section titled “Custom item rendering”For full control over a single row’s markup — multi-line layouts, badges, custom typography — render each option yourself.
Use the renderItem prop. It receives the option and a boolean indicating whether the option is currently selected.
Use the #item=”{ option, isSelected, index }” scoped slot.
Loading Code Block...Custom content
Section titled “Custom content”Use options, showSearch, and multiple props are ignored.
Loading Code Block...Controlled state
Section titled “Controlled state”You can control the dropdown’s open/close state externally with
Loading Code Block...DropdownMenu Props
Section titled “DropdownMenu Props”Vue Slot Reference
The Vue component uses named slots for the trigger, custom content, and footer areas.
| Slot Name | Default | Type | Description |
|---|---|---|---|
| #trigger | - | slot | Required. The element that opens the dropdown when clicked. Wrapped in a button internally. |
| #customContent | - | slot | Replaces the default options list with fully custom template content. When provided, options, showSearch, and multiple are ignored. |
| #item | - | scoped slot — { option, isSelected, index } | Custom row renderer. When provided, replaces the default option markup for every row. React equivalent: the `renderItem` prop. |
| #itemRight | - | scoped slot — { option, isSelected } | Right-aligned content rendered on each option row. Useful for keyboard shortcuts, badges, or status indicators. React equivalent: `option.rightContent`. |
| #footer | - | slot | Optional content rendered below the options list, separated by a top border. Useful for actions like 'Add new item'. |
Vue Events
| Event | Default | Type | Description |
|---|---|---|---|
| selected | - | (item: Option | string) => void | Emitted when a single option is selected (or when in navigation mode). In navigation mode, emits the `href` string. |
| update:isOpen | - | (value: boolean) => void | Emitted when the dropdown opens or closes. Use with v-model:isOpen for two-way binding. |
Accessibility
Section titled “Accessibility”- The trigger element has
aria-expandedandaria-haspopup="true"attributes. - The dropdown panel uses
role="menu"and individual options userole="menuitem". - Keyboard navigation is supported:
- When
disabledis true,. - Search input events are stopped from propagating to prevent the menu from closing while typing.
Behaviour notes
Section titled “Behaviour notes”- Multi-select toggle. In
multiplemode, clicking a selected option correctly removes it from the selection (and clicking an unselected option adds it). All selection logic operates on the boundvalue/v-modeldirectly. - Search resets on close. When the menu closes, the inline search input is cleared so re-opening always shows the full options list.
onClickbypasses selection. Options with anonClickhandler invoke that handler and close the menu without mutating the dropdown’sselectedvalue — useful for action-style items in a selection-style dropdown.- Disabled options are skipped during keyboard navigation (Arrow keys + Enter) and cannot be selected by click.