Dropdown Menu
Displays a menu of actions triggered by a buttonDisplays a menu of actions or options triggered by a button. Use dropdown menus for contextual actions, navigation options, and selection interfaces where space is limited.
This component is built on Radix UI Dropdown Menu. For the full primitive API reference, see the Radix documentation.
Installation
Usage
Anatomy
The dropdown menu is composed of several parts:
Props
Root
Trigger
Content
Item
CheckboxItem
RadioGroup
RadioItem
Sub
In drill-down mode, open and defaultOpen push the submenu onto the navigation stack, and onOpenChange reports every push and pop. A controlled open is applied when it changes: the user can still navigate in and out, and your onOpenChange handler is where you keep open in sync.
SubTrigger
SubContent
SubContent has no submenuBehavior; the parent Content decides it. In drill-down mode the visual and positioning props do not apply, because the panel renders inline in the parent content.
Variants
Solid
Default variant with an opaque background for standard interfaces.
Soft
Subtle background with reduced contrast for content-heavy interfaces.
Sizes
Size 1
Compact size for dense interfaces and toolbars.
Size 2
Standard size for most interfaces.
Colors
Use the color prop on items to communicate intent. Destructive actions should use red or crimson.
Material
Solid
Opaque background for standard interfaces.
Translucent
Frosted glass effect for depth over images or dynamic backgrounds. Item text reads the strong ink by default.
Shortcuts
Display keyboard shortcuts using the shortcut prop on items.
Labels
Use Label to add section headings within the menu.
Groups
Use Group to logically group related items.
Checkbox Items
Use CheckboxItem for toggleable options within the menu.
Radio Items
Use RadioGroup and RadioItem for mutually exclusive options.
Submenus
Use Sub, SubTrigger, and SubContent for nested navigation.
Submenu Behavior
The submenuBehavior prop controls how submenus appear and interact. There are two modes:
Cascade (Default)
Submenus open as floating panels to the side of the trigger, using portals. This is the standard desktop behavior.
Drill-Down
Submenus replace the current menu content inline with a back button, similar to mobile navigation patterns. This prevents horizontal overflow on small screens.
The label prop on Sub sets the text of the back row at the top of the panel. It defaults to "Back". Screen readers hear "Back from Settings" for label="Settings", and the panel is a group named after its trigger.
Only the levels you have navigated into are mounted, so a menu with many submenus opens as fast as a flat one. Arrow keys, typeahead and Home/End only reach the items on screen.
Responsive
Use a responsive object to switch between behaviors at different breakpoints. This provides the best experience on both mobile and desktop.
Breakpoint values: initial (default), xs (520px), sm (768px), md (1024px), lg (1280px), xl (1640px).
Trigger Icon
Use TriggerIcon to add a dropdown indicator to custom triggers.
Virtualization
For menus with many items (hundreds or thousands), use the virtualized prop with VirtualMenu to render only visible items. This dramatically improves performance by keeping the DOM small.
Simple Usage
Use itemLabel for basic text items:
How It Works
- Set
virtualizedonContentto skip the built-in ScrollArea - Use
VirtualMenuwith your items array - Provide
itemLabel(for simple text) orrenderItem(for custom rendering) - Set a fixed
heighton VirtualMenu (required for virtualization)
VirtualMenu Props
You must provide either itemLabel or renderItem.
Custom Rendering with renderItem
For custom item layouts, pass a memoized component to renderItem:
Important: The renderItem component must:
- Be wrapped in
React.memofor optimal performance - Spread
styleand other props ontoVirtualMenu.Item
RenderItem Props
Props passed to your renderItem component:
Variable Height Items
Use a function for estimatedItemSize when items have different heights:
Keyboard Navigation
VirtualMenu supports full keyboard navigation:
Controlled
Control the open state for programmatic menu management.
Accessibility
Dropdown Menu follows the WAI-ARIA Menu Button pattern and includes:
Keyboard Navigation
Screen Readers
- Proper
role="menu"androle="menuitem"attributes aria-haspopupon trigger indicates menu availabilityaria-expandedreflects open statearia-checkedfor checkbox and radio itemsaria-disabledfor disabled itemsaria-keyshortcutson items with ashortcut; the visual hint is hidden from screen readers so it is not read as part of the item name- Drill-down panels are groups named after their trigger, and the back row is named "Back from …"
- Focus management returns to trigger on close
Focus Management
- Focus is trapped within menu when open
- Focus returns to trigger when menu closes
- Submenus manage focus independently
- In drill-down mode, keyboard navigation moves focus to the first item of the new panel and back to the SubTrigger on return. The scroll position of each level is restored
- A drill-down menu always reopens at its root level
Changelog
Added
- Built on Radix UI Dropdown Menu primitive
materialprop for solid/translucent backgrounds- Integrated
ScrollAreafor long menus shortcutprop for keyboard shortcut display usingKbdcomponent- Theme integration for accent colors and materials
- Drill-down submenu behavior via
submenuBehaviorprop for mobile-friendly navigation labelprop onSubfor custom back button text in drill-down mode- Responsive submenu behavior with breakpoint-based switching between cascade and drill-down modes
- Drill-down animations with direction-aware slide transitions (slides from right when entering submenu, from left when going back)
- Respects
prefers-reduced-motionfor drill-down animations - Virtualization support via
virtualizedprop andVirtualMenucomponent for rendering large lists efficiently
Fixed
- Drill-down SubTrigger and back row are real menu items: arrow keys, typeahead and
Home/Endreach them - Drill-down focus moves into the new panel and back to the SubTrigger instead of dropping to the page
EscapeandArrow Leftgo back one drill-down level;Arrow Rightopens a submenu- Drill-down mounts only the levels on the navigation stack instead of every submenu
- Drill-down panels nested in groups and radio groups now show
- SubTrigger forwards its props and honors
disabledin drill-down mode Subhonorsopen,defaultOpenandonOpenChangein drill-down mode- Switching between cascade and drill-down no longer remounts the menu
- A responsive
sizeno longer places submenus at the viewport origin SubContentuses its ownsize,variant,colorandmaterial, and supportsvirtualized- Menus follow a nested
Themematerial TriggerIconkeeps itsclassName- Label and muted text meet AA contrast
Removed
highContrastonContentandSubContent. A gray menu highlights with step 12 on its own, and item text reads the strong ink by default.
Deprecated
panelBackgroundprop in favor ofmaterialprop
© 2026 Kushagra Dhawan. Licensed under MIT. GitHub.