Skip to main content

An accessible dropdown and context menu that displays a list of actions or options.

typo3 ui:add menu

Read more about installing Components and Primitives.

Organize items into logical groups with their own labels.

Pass asChild="{true}" on menu.item to render the item's attributes and behavior directly onto a single child element, like a plain <a href>, so it behaves like real navigation, including keyboard activation.

Use menu.checkboxItem for items that toggle independently of each other.

Use menu.radioItem with a shared name for mutually exclusive options.

A submenu is just another menu.root, linked to its parent by two explicit ids: give the submenu's menu.root a rootId and point its parentId back at the parent menu's own rootId, then render a menu.triggerItem inside the parent's own content with a childId matching the submenu's rootId. The submenu itself doesn't need to live anywhere near the parent's markup - it's linked entirely by id.

Use menu.contextTrigger to open the menu on right-click instead of (or in addition to) a regular trigger.

Give several menu.trigger elements different values to share a single menu instance between them.

By default menu.content portals to the end of the document body, same as Select. Pass portalled="{false}" when nesting a menu inside another portalled/focus-trapped element, like a dialog, so it stays within that element's DOM subtree instead.

The following tables cover the available props of the Fluid Primitives. For a full list of available client side props and methods, see the Zag.js Machine API.

menu.root

Provides shared menu state to the rest of the parts. Renders no element of its own.

NameDescriptionRequiredDefault
closeOnSelectboolean
Whether to close the menu when an option is selected.
No
true
compositeboolean
Whether the menu is composed with other composite widgets like a combobox or tabs.
No
true
typeaheadboolean
Whether pressing printable characters should trigger typeahead navigation.
No
true
loopFocusboolean
Whether to loop the keyboard navigation.
No
false
positioningarray
The options used to dynamically position the menu.
No
{
    "placement": "bottom-start",
    "gutter": 8
}
defaultOpenboolean
The initial open state of the menu when rendered. Use when you don't need to control the open state of the menu.
No
false
defaultHighlightedValuestring
The initial highlighted value of the menu item when rendered.
No
-
defaultTriggerValuestring
The initial trigger value when rendered, for a menu with multiple triggers.
No
-
ariaLabelstring
The accessibility label for the menu. Forwarded to the machine as `aria-label`.
No
-
parentIdstring
The `rootId` of the parent menu this menu is a submenu of. Must match a `menu.triggerItem`'s `childId` on that parent, pointing back at this menu's own `rootId` - see the Nested Menu docs example.
No
-
rootIdstring
The root ID of the component, used for hydration and identification.
No
-
idsarray
The IDs of of the component parts for composition.
No
[]
controlledboolean
If true, the component is meant to be initialized manually inside another component
No
false

menu.trigger

Opens and closes the menu. Renders a <button> element.

NameDescriptionRequiredDefault
valuestring
The value that identifies this specific trigger, for a menu with multiple triggers.
No
-
asChildboolean
If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props.
No
-
classstring
The CSS class(es) to be applied to the component.
No
-
attributesarray
Additional attributes that should be rendered on the component where ui:attributes is used.
No
[]

Rendered data attributes

AttributeDescription
data-scopemenu
data-parttrigger
data-placementThe placement of the trigger
data-sideThe side of the trigger that the trigger is positioned on
data-valueThe value of the item
data-currentPresent when current
data-controls
data-state"open" | "closed"

menu.contextTrigger

Opens the menu at the cursor position on right-click. Renders a <div> element.

NameDescriptionRequiredDefault
valuestring
The value that identifies this specific context trigger, for a menu with multiple context triggers.
No
-
asChildboolean
If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props.
No
-
classstring
The CSS class(es) to be applied to the component.
No
-
attributesarray
Additional attributes that should be rendered on the component where ui:attributes is used.
No
[]

Rendered data attributes

AttributeDescription
data-scopemenu
data-partcontext-trigger
data-valueThe value of the item
data-currentPresent when current
data-state"open" | "closed"

menu.content

Contains the menu items. Renders a <div> element.

NameDescriptionRequiredDefault
asChildboolean
If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props.
No
-
classstring
The CSS class(es) to be applied to the component.
No
-
attributesarray
Additional attributes that should be rendered on the component where ui:attributes is used.
No
[]

Rendered data attributes

AttributeDescription
data-scopemenu
data-partcontent
data-state"open" | "closed"
data-nestedmenu
data-has-nestedmenu
data-placementThe placement of the content
data-sideThe side of the trigger that the content is positioned on

menu.item

A selectable menu action. Renders a <div> element.

NameDescriptionRequiredDefault
valuestring
The unique value of the menu item.
Yes
-
disabledboolean
Whether the menu item is disabled.
No
-
valueTextstring
The textual value of the item, used for typeahead navigation. Falls back to the item's text content when omitted.
No
-
asChildboolean
If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props.
No
-
classstring
The CSS class(es) to be applied to the component.
No
-
attributesarray
Additional attributes that should be rendered on the component where ui:attributes is used.
No
[]

Rendered data attributes

AttributeDescription
data-scopemenu
data-partitem
data-disabledPresent when disabled
data-highlightedPresent when highlighted
data-valueThe value of the item
data-valuetextThe human-readable value

menu.checkboxItem

A menu item that toggles independently of other items. Renders a <div> element.

NameDescriptionRequiredDefault
valuestring
The unique value of the checkbox item.
Yes
-
checkedboolean
Whether the checkbox item is checked when rendered.
No
false
disabledboolean
Whether the checkbox item is disabled.
No
-
valueTextstring
The textual value of the item, used for typeahead navigation. Falls back to the item's text content when omitted.
No
-
asChildboolean
If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props.
No
-
classstring
The CSS class(es) to be applied to the component.
No
-
attributesarray
Additional attributes that should be rendered on the component where ui:attributes is used.
No
[]

menu.radioItem

A menu item that's mutually exclusive with other radio items sharing the same name. Renders a <div> element.

NameDescriptionRequiredDefault
valuestring
The unique value of the radio item.
Yes
-
checkedboolean
Whether the radio item is checked when rendered.
No
false
disabledboolean
Whether the radio item is disabled.
No
-
valueTextstring
The textual value of the item, used for typeahead navigation. Falls back to the item's text content when omitted.
No
-
namestring
Groups radio items so selecting one unchecks the others sharing the same `name`.
No
-
asChildboolean
If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props.
No
-
classstring
The CSS class(es) to be applied to the component.
No
-
attributesarray
Additional attributes that should be rendered on the component where ui:attributes is used.
No
[]

menu.itemGroup

Groups related items together. Renders a <div> element.

NameDescriptionRequiredDefault
valuestring
The value identifier of the item group. Picked up automatically by a `menu.itemGroupLabel` nested inside it.
Yes
-
asChildboolean
If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props.
No
-
classstring
The CSS class(es) to be applied to the component.
No
-
attributesarray
Additional attributes that should be rendered on the component where ui:attributes is used.
No
[]

menu.itemGroupLabel

Labels an itemGroup. Renders a <div> element.

NameDescriptionRequiredDefault
asChildboolean
If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props.
No
-
classstring
The CSS class(es) to be applied to the component.
No
-
attributesarray
Additional attributes that should be rendered on the component where ui:attributes is used.
No
[]

menu.separator

A visual divider between items. Renders a <div> element.

NameDescriptionRequiredDefault
asChildboolean
If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props.
No
-
classstring
The CSS class(es) to be applied to the component.
No
-
attributesarray
Additional attributes that should be rendered on the component where ui:attributes is used.
No
[]

menu.triggerItem

Opens a nested submenu from within another menu's content. Renders a <div> element.

NameDescriptionRequiredDefault
childIdstring
The `rootId` of the submenu (its `menu.root`'s `rootId`) that this item opens. That submenu's own `parentId` must point back at this menu's `rootId`.
Yes
-
asChildboolean
If true the component uses its child only without the component template. Like Radix UI asChild or Base UI render props.
No
-
classstring
The CSS class(es) to be applied to the component.
No
-
attributesarray
Additional attributes that should be rendered on the component where ui:attributes is used.
No
[]

Machine JavaScript API

NameTypeDescription
openbooleanWhether the menu is open
setOpen(open: boolean) => voidFunction to open or close the menu
triggerValuestring | nullThe trigger value
setTriggerValue(value: string | null) => voidFunction to set the trigger value
highlightedValuestring | nullThe id of the currently highlighted menuitem
setHighlightedValue(value: string) => voidFunction to set the highlighted menuitem
setParent(parent: MenuService) => voidFunction to register a parent menu. This is used for submenus
setChild(child: MenuService) => voidFunction to register a child menu. This is used for submenus
reposition(options?: Partial<PositioningOptions>) => voidFunction to reposition the popover
getOptionItemState(props: OptionItemProps) => OptionItemStateReturns the state of the option item
getItemState(props: ItemProps) => ItemStateReturns the state of the menu item
addItemListener(props: ItemListenerProps) => VoidFunction | undefinedSetup the custom event listener for item selection event

Accessibility

KeyDescription
SpaceActivates/Selects the highlighted item
EnterActivates/Selects the highlighted item
ArrowDownHighlights the next item in the menu
ArrowUpHighlights the previous item in the menu
ArrowRightArrowLeftWhen focus is on trigger, opens or closes the submenu depending on reading direction.
EscCloses the menu and moves focus to the trigger
<primitives:menu.root>
    <primitives:menu.trigger>
        <primitives:menu.indicator />
    </primitives:menu.trigger>
    <primitives:menu.contextTrigger />
    <primitives:menu.positioner>
        <primitives:menu.arrow />
        <primitives:menu.content>
            <primitives:menu.item>
                <primitives:menu.itemText />
            </primitives:menu.item>
            <primitives:menu.checkboxItem>
                <primitives:menu.itemIndicator />
                <primitives:menu.itemText />
            </primitives:menu.checkboxItem>
            <primitives:menu.radioItem>
                <primitives:menu.itemIndicator />
                <primitives:menu.itemText />
            </primitives:menu.radioItem>
            <primitives:menu.separator />
            <primitives:menu.itemGroup>
                <primitives:menu.itemGroupLabel />
            </primitives:menu.itemGroup>

            <f:comment><!-- Opens the submenu below, matched by rootId/childId --></f:comment>
            <primitives:menu.triggerItem childId="submenu" />
        </primitives:menu.content>
    </primitives:menu.positioner>
</primitives:menu.root>

<f:comment><!-- A submenu: linked to its parent by id, not by nesting --></f:comment>
<primitives:menu.root rootId="submenu" parentId="parent-rootId">
    <primitives:menu.positioner>
        <primitives:menu.content>
            <primitives:menu.item />
        </primitives:menu.content>
    </primitives:menu.positioner>
</primitives:menu.root>