Menu
import {Menu} from "@qualcomm-ui/react/menu"Examples
Item Customization
Compose the menu to include icons and commands.
Context Menu
Demonstrates how to trigger a menu on right-click or other context events.
Nested Menus
Compose nested menus by nesting <Menu.Root> components inside each other.
<Menu.Root>
<Menu.Trigger>
<Menu.Button emphasis="primary">Show Menu</Menu.Button>
</Menu.Trigger>
<Portal>
<Menu.Positioner>
<Menu.Content>
<Menu.Item value="new-txt">New Text File</Menu.Item>
<Menu.Item value="new-file">New File...</Menu.Item>
<Menu.Root positioning={{gutter: 2, placement: "right-start"}}>
<Menu.TriggerItem value="open-recent">
Open Recent
</Menu.TriggerItem>
<Portal>
<Menu.Positioner>
<Menu.Content>
<Menu.Item value="file-1">File 1</Menu.Item>
<Menu.Item value="file-2">File 2</Menu.Item>
<Menu.Item value="file-3">File 3</Menu.Item>
</Menu.Content>
</Menu.Positioner>
</Portal>
</Menu.Root>
</Menu.Content>
</Menu.Positioner>
</Portal>
</Menu.Root>Links
Menu items can be links using polymorphic composition. Use the render prop on the <Menu.Item> to specify the element type.
<Menu.Content>
<Menu.Item
render={
<a href="https://react.dev" rel="noreferrer" target="_blank" />
}
value="react"
>
<Menu.ItemStartIcon icon={ExternalLink} />
React
</Menu.Item>
<Menu.Item
render={
<a
href="https://angular.dev"
rel="noreferrer"
target="_blank"
/>
}
value="angular"
>
<Menu.ItemStartIcon icon={ExternalLink} />
Angular
</Menu.Item>
</Menu.Content>Groups
Use the <Menu.ItemGroup> component to group menu items.
Item Types
There are three item types, each corresponding to one of the three types of aria menu item roles:
<Menu.Item>—menuitem<Menu.RadioItem>—menuitemradio<Menu.CheckboxItem>—menuitemcheckbox
Checkbox Items
There are two appearance options:
- For a checkbox appearance, render the
<Menu.CheckboxItemControl>element as a child of the item. - Render the
<Menu.ItemIndicator />element for a simple selection indicator.
<Menu.ItemGroup>
<Menu.ItemGroupLabel>Choose an option</Menu.ItemGroupLabel>
<Menu.CheckboxItem value="item-1-1">
<Menu.CheckboxItemControl />
<Menu.ItemLabel>Option 1</Menu.ItemLabel>
</Menu.CheckboxItem>
<Menu.CheckboxItem value="item-1-2">
<Menu.CheckboxItemControl />
<Menu.ItemLabel>Option 2</Menu.ItemLabel>
</Menu.CheckboxItem>
</Menu.ItemGroup>
<Menu.ItemGroup>
<Menu.ItemGroupLabel>Choose an option</Menu.ItemGroupLabel>
<Menu.CheckboxItem value="item-2-1">
<Menu.ItemLabel>Option 1</Menu.ItemLabel>
<Menu.ItemIndicator />
</Menu.CheckboxItem>
<Menu.CheckboxItem value="item-2-2">
<Menu.ItemLabel>Option 2</Menu.ItemLabel>
<Menu.ItemIndicator />
</Menu.CheckboxItem>
</Menu.ItemGroup>Checkbox Selection State
Illustrates how to manage and reflect the checked state of checkbox menu items.
<Menu.ItemGroup>
<Menu.ItemGroupLabel>Choose an option</Menu.ItemGroupLabel>
{items.map(({label, value}) => (
<Menu.CheckboxItem
key={value}
checked={checkboxState[value] || false}
onCheckedChange={(checked) => onChange(value, checked)}
value={value}
>
<Menu.ItemLabel>{label}</Menu.ItemLabel>
<Menu.ItemIndicator />
</Menu.CheckboxItem>
))}
</Menu.ItemGroup>Radio Group
Demonstrates how to group radio menu items so only one can be selected at a time.
Controlled State
The menu's visibility can be controlled via the open, onOpenChange, and defaultOpen props.
- Use
opento explicitly set whether the menu is open (controlled mode). - Use
onOpenChangeto be notified when the menu requests to open or close. - Use
defaultOpento set the initial open state when you don't need to control it yourself (uncontrolled mode).
In controlled mode, the open prop should be updated in response to onOpenChange events to reflect the desired visibility.
Placement
Configure the menu's placement using the positioning.placement prop.
Sizes
Use the size prop to control the size of the menu. The default size is md. The demo features the small (sm) size.
Anchor Point
Use the positioning.anchorPoint prop to control the anchor point of the menu.
Avatar
Here's an example that composes the Menu with the Avatar component to display a user account menu.
Within Dialog
When using the Menu inside a Dialog, don't render the <Menu.Positioner> within a <Portal> element.
Hide When Detached
Use the positioning.hideWhenDetached prop to hide the menu when it's detached from the trigger.
API
<Menu.Root>
| Prop | Type | Default |
|---|---|---|
The positioning point for the menu. Can be set by the context menu trigger or
the button trigger. | { | |
Whether to close the menu when an option is selected | boolean | true |
Whether the menu is composed with other composite widgets like a combobox or tabs | boolean | true |
The initial highlighted value of the menu item when rendered.
Use when you don't need to control the highlighted value of the menu item. | string | |
The initial open state of the menu when rendered.
Use when you don't need to control the open state of the menu. | boolean | |
The document's text/writing direction. | 'ltr' | 'rtl' | 'ltr' |
A root node to correctly resolve document in custom environments. i.e.,
Iframes, Electron. | () => | |
The controlled highlighted value of the menu item. | string | |
id attribute. If
omitted, a unique identifier will be automatically generated for accessibility. | string | |
Whether to synchronize the present change immediately or defer it to the next
frame | boolean | |
When true, the component will not be rendered in the DOM until it becomes
visible or active. | boolean | false |
Whether to loop the keyboard navigation. | boolean | false |
Function to navigate to the selected item if it's an anchor element | (details: { | |
Function called when the escape key is pressed | ( | |
Function called when the animation ends in the closed state | VoidFunction | |
Function called when the focus is moved outside the component | ( | |
Function called when the highlighted menu item changes. | ( | |
Function called when an interaction happens outside the component | ( | |
Function called when the menu opens or closes | ( | |
Function called when the pointer is pressed down outside the component | ( | |
Function called when this layer is closed due to a parent layer being closed | ( | |
Function called when a menu item is selected. | ( | |
The controlled open state of the menu | boolean | |
The options used to dynamically position the menu | ||
Whether the node is present (controlled by the user) | boolean | |
'sm' | 'md' | ||
Whether to allow the initial presence animation. | boolean | false |
Whether the pressing printable characters should trigger typeahead navigation | boolean | true |
When true, the component will be completely removed from the DOM when it
becomes inactive or hidden, rather than just being hidden with CSS. | boolean | false |
{
x: number
y: number
}
booleanbooleanstringboolean'ltr' | 'rtl'
() =>
| Node
| ShadowRoot
| Document
stringstringbooleanbooleanboolean(details: {
href: string
node: HTMLAnchorElement
value: string
}) => void
(
event: KeyboardEvent,
) => void
VoidFunction(
event: FocusOutsideEvent,
) => void
(
value: string,
) => void
(
event: InteractOutsideEvent,
) => void
(
open: boolean,
) => void
(
event: PointerDownOutsideEvent,
) => void
(
event: CustomEvent<{
originalIndex: number
originalLayer: HTMLElement
targetIndex: number
targetLayer: HTMLElement
}>,
) => void
(
value: string,
) => void
booleanboolean'sm' | 'md'
booleanbooleanbooleanPositioningOptions
The positioning prop accepts an object with the following shape:
| Prop | Type | Default |
|---|---|---|
The minimum padding between the arrow and the floating element's corner. | number | 4 |
The overflow boundary of the reference element | () => | |
Whether the popover should fit the viewport. | boolean | |
Whether to flip the placement when the floating element overflows the boundary. | | boolean | true |
Function that returns the anchor rect | ( | |
The main axis offset or gap between the reference and floating element | number | 8 |
Whether the popover should be hidden when the reference element is detached | boolean | |
Options to activate auto-update listeners | | boolean | true |
The offset of the floating element | { | |
Function called when the placement is computed | ( | |
Function called when the floating element is positioned or not | (data: { | |
The virtual padding around the viewport edges to check for overflow | number | |
Whether the floating element can overlap the reference element | boolean | false |
The initial placement of the floating element | | 'bottom' | 'bottom' |
Whether to make the floating element same width as the reference element | boolean | |
The secondary axis offset or gap between the reference and floating elements | number | |
Whether the popover should slide when it overflows. | boolean | |
The strategy to use for positioning | | 'absolute' | 'absolute' |
A callback that will be called when the popover needs to calculate its
position. | (data: { |
number() =>
| 'clippingAncestors'
| Element
| Array<Element>
| {
height: number
width: number
x: number
y: number
}
boolean| boolean
| Array<
| 'bottom'
| 'bottom-end'
| 'bottom-start'
| 'left'
| 'left-end'
| 'left-start'
| 'right'
| 'right-end'
| 'right-start'
| 'top'
| 'top-end'
| 'top-start'
>
(
element:
| HTMLElement
| VirtualElement,
) => {
height?: number
width?: number
x?: number
y?: number
}
numberboolean| boolean
| {
ancestorResize?: boolean
ancestorScroll?: boolean
animationFrame?: boolean
elementResize?: boolean
layoutShift?: boolean
}
{
crossAxis?: number
mainAxis?: number
}
(
data: ComputePositionReturn,
) => void
(data: {
placed: boolean
}) => void
numberboolean| 'bottom'
| 'bottom-end'
| 'bottom-start'
| 'left'
| 'left-end'
| 'left-start'
| 'right'
| 'right-end'
| 'right-start'
| 'top'
| 'top-end'
| 'top-start'
booleannumberboolean| 'absolute'
| 'fixed'
(data: {
updatePosition: () => Promise<void>
}) => void | Promise<void>
Element API
The following describes the individual subcomponents of the Menu component.
<Menu.Button>
| Prop | Type | Default |
|---|---|---|
The density of the button. Governs padding and height. | | 'default' | 'default' |
Controls whether the component is interactive. When true, pointer/focus
events are blocked, and the component is visually dimmed. | boolean | false |
The style variant of the button. Governs colors. | | 'neutral' | 'neutral' |
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement | |
The size of the component and its icons. | | 'sm' | 'md' |
| LucideIcon | ||
The style variant of the button. Governs colors. | | 'fill' | 'fill' |
| 'default'
| 'compact'
booleantrue, pointer/focus
events are blocked, and the component is visually dimmed.| 'neutral'
| 'primary'
| 'danger'
| 'white-persistent'
| 'black-persistent'
| ReactElement
| ((
props: object,
) => ReactElement)
| 'sm'
| 'md'
| 'lg'
| LucideIcon
| ReactNode
LucideIcon,
the size will automatically match the size prop. Supply as a
ReactElement for additional customization.| 'fill'
| 'ghost'
| 'outline'
<Menu.IconButton>
| Prop | Type | Default |
|---|---|---|
The density of the button. Governs padding and height. | | 'default' | 'default' |
Controls whether the component is interactive. When true, pointer/focus
events are blocked, and the component is visually dimmed. | boolean | false |
The style variant of the button. Governs colors. | | 'neutral' | 'neutral' |
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement | |
The size of the component and its icons. | | 'sm' | 'md' |
The style variant of the button. Governs colors. | | 'fill' | 'fill' |
| 'default'
| 'compact'
booleantrue, pointer/focus
events are blocked, and the component is visually dimmed.| 'neutral'
| 'primary'
| 'danger'
| 'white-persistent'
| 'black-persistent'
| ReactElement
| ((
props: object,
) => ReactElement)
| 'sm'
| 'md'
| 'lg'
| 'fill'
| 'ghost'
| 'outline'
<Menu.Content>
| Prop | Type |
|---|---|
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
| ReactElement
| ((
props: object,
) => ReactElement)
<Menu.Trigger>
| Prop | Type |
|---|---|
React children Render Prop | |
id attribute. If
omitted, a unique identifier will be automatically generated for accessibility. | string |
string<Menu.Item>
| Prop | Type |
|---|---|
The unique value of the menu item option. | string |
Whether the menu should be closed when the option is selected. | boolean |
Whether the menu item is disabled | boolean |
The function to call when the item is selected | () => void |
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
The textual value of the option. Used in typeahead navigation of the menu.
If not provided, the text content of the menu item will be used. | string |
stringbooleanboolean() => void
| ReactElement
| ((
props: object,
) => ReactElement)
string<Menu.ItemAccessory>
| Prop | Type |
|---|---|
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
| ReactElement
| ((
props: object,
) => ReactElement)
<Menu.ItemCommand>
| Prop | Type |
|---|---|
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
| ReactElement
| ((
props: object,
) => ReactElement)
<Menu.ItemLabel>
| Prop | Type |
|---|---|
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
| ReactElement
| ((
props: object,
) => ReactElement)
<Menu.ItemDescription>
| Prop | Type |
|---|---|
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
| ReactElement
| ((
props: object,
) => ReactElement)
<Menu.ItemControl>
MenuItemControlProps<Menu.ItemGroup>
<Menu.ItemGroupLabel>
| Prop | Type |
|---|---|
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
| ReactElement
| ((
props: object,
) => ReactElement)
<Menu.ItemStartIcon>
<Menu.ItemIndicator>
| Prop | Type |
|---|---|
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
| ReactElement
| ((
props: object,
) => ReactElement)
<Menu.CheckboxItem>
| Prop | Type |
|---|---|
The value of the option | string |
Whether the option is checked | boolean |
Whether the menu should be closed when the option is selected. | boolean |
Whether the menu item is disabled | boolean |
Function called when the option state is changed | ( |
The function to call when the item is selected | () => void |
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
The textual value of the option. Used in typeahead navigation of the menu.
If not provided, the text content of the menu item will be used. | string |
stringbooleanbooleanboolean(
checked: boolean,
) => void
() => void
| ReactElement
| ((
props: object,
) => ReactElement)
string<Menu.CheckboxItemControl>
| Prop | Type | Default |
|---|---|---|
<Checkbox.IndicatorIcon /> | ||
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
| ReactElement
| ((
props: object,
) => ReactElement)
<Menu.RadioItem>
| Prop | Type |
|---|---|
The unique value of the menu item option. | string |
Whether the menu should be closed when the option is selected. | boolean |
Whether the menu item is disabled | boolean |
The function to call when the item is selected | () => void |
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
The textual value of the option. Used in typeahead navigation of the menu.
If not provided, the text content of the menu item will be used. | string |
stringbooleanboolean() => void
| ReactElement
| ((
props: object,
) => ReactElement)
string<Menu.RadioItemControl>
| Prop | Type |
|---|---|
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
| ReactElement
| ((
props: object,
) => ReactElement)
<Menu.RadioItemGroup>
| Prop | Type |
|---|---|
string | |
( | |
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
string |
string(
value: string,
) => void
| ReactElement
| ((
props: object,
) => ReactElement)
string<Menu.Separator>
| Prop | Type |
|---|---|
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement |
| ReactElement
| ((
props: object,
) => ReactElement)
<Menu.TriggerItem>
<button>
element by default.| Prop | Type | Default |
|---|---|---|
The unique value of the menu item option. | string | |
Whether the menu should be closed when the option is selected. | boolean | |
Whether the menu item is disabled | boolean | |
Icon to display next to the label, which indicates that this menu item is a
trigger for a submenu. | | LucideIcon | ChevronRight |
The function to call when the item is selected | () => void | |
Allows you to replace the component's HTML element with a different tag or component. Learn more | | ReactElement | |
The textual value of the option. Used in typeahead navigation of the menu.
If not provided, the text content of the menu item will be used. | string |
stringbooleanboolean| LucideIcon
| ReactNode
() => void
| ReactElement
| ((
props: object,
) => ReactElement)
string