Components
Menu

Menu

A list of options that appears when a user interacts with a button.

You can explore the menu component in the following curated examples.

Anatomy

To set up the menu correctly, you'll need to understand its anatomy and how we name its parts.

Each part includes a data-part attribute to help identify them in the DOM.

Examples

Learn how to use the Menu component in your project. Let's take a look at the most basic example:

<script setup lang="ts">
import { Menu } from '@ark-ui/vue/menu'
</script>

<template>
  <Menu.Root>
    <Menu.Trigger>
      Open menu
      <Menu.Indicator>➡️</Menu.Indicator>
    </Menu.Trigger>
    <Menu.Positioner>
      <Menu.Content>
        <Menu.Item value="react">React</Menu.Item>
        <Menu.Item value="solid">Solid</Menu.Item>
        <Menu.Item value="vue">Vue</Menu.Item>
      </Menu.Content>
    </Menu.Positioner>
  </Menu.Root>
</template>

Listening to item selection

Pass the onSelect prop to the Menu component to perform some custom logic when an item is selected. The callback is invoked with the id of the item.

<script setup lang="ts">
import { Menu } from '@ark-ui/vue/menu'
import { ref } from 'vue'

const isOpen = ref(false)
</script>

<template>
  <button @click="isOpen = !isOpen">Trigger from the outside</button>
  <Menu.Root :open="isOpen">
    <Menu.Trigger>Open menu</Menu.Trigger>
    <Menu.Positioner>
      <Menu.Content>
        <Menu.Item value="react">React</Menu.Item>
        <Menu.Item value="solid">Solid</Menu.Item>
        <Menu.Item value="vue">Vue</Menu.Item>
      </Menu.Content>
    </Menu.Positioner>
  </Menu.Root>
</template>

Grouping menu items

When the number of menu items gets much, it might be useful to group related menu items. To achieve this, render the Menu.ItemGroup component around the Menu.Item components. The Menu.ItemGroupLabel component can be used to add a label to the group.

<script setup lang="ts">
import { Menu } from '@ark-ui/vue/menu'
</script>

<template>
  <Menu.Root>
    <Menu.Trigger>Open menu</Menu.Trigger>
    <Menu.Positioner>
      <Menu.Content>
        <Menu.ItemGroup>
          <Menu.ItemGroupLabel>JS Frameworks</Menu.ItemGroupLabel>
          <Menu.Item value="react">React</Menu.Item>
          <Menu.Item value="solid">Solid</Menu.Item>
          <Menu.Item value="vue">Vue</Menu.Item>
        </Menu.ItemGroup>
        <Menu.ItemGroup>
          <Menu.ItemGroupLabel>CSS Frameworks</Menu.ItemGroupLabel>
          <Menu.Item value="panda">Panda</Menu.Item>
          <Menu.Item value="tailwind">Tailwind</Menu.Item>
        </Menu.ItemGroup>
      </Menu.Content>
    </Menu.Positioner>
  </Menu.Root>
</template>

Separating menu items

To separate menu items, render the Menu.Separator component.

<script setup lang="ts">
import { Menu } from '@ark-ui/vue/menu'
</script>

<template>
  <Menu.Root>
    <Menu.Trigger>Open menu</Menu.Trigger>
    <Menu.Positioner>
      <Menu.Content>
        <Menu.Item value="react">React</Menu.Item>
        <Menu.Item value="solid">Solid</Menu.Item>
        <Menu.Separator />
        <Menu.Item value="vue">Vue</Menu.Item>
      </Menu.Content>
    </Menu.Positioner>
  </Menu.Root>
</template>

Context menu

To show the menu when a trigger element is right-clicked, use the Menu.ContextTrigger component.

Context menus are also opened during a long-press of roughly 700ms when the pointer is pen or touch.

<script setup lang="ts">
import { Menu } from '@ark-ui/vue/menu'
</script>

<template>
  <Menu.Root>
    <Menu.ContextTrigger>Right click me</Menu.ContextTrigger>
    <Menu.Positioner>
      <Menu.Content>
        <Menu.Item value="react">React</Menu.Item>
        <Menu.Item value="solid">Solid</Menu.Item>
        <Menu.Item value="vue">Vue</Menu.Item>
      </Menu.Content>
    </Menu.Positioner>
  </Menu.Root>
</template>

Nested menu

To show a nested menu, render another Menu component and use the Menu.TriggerItem component to open the submenu.

<script setup lang="ts">
import { Menu } from '@ark-ui/vue/menu'
</script>

<template>
  <Menu.Root>
    <Menu.Trigger>Open menu</Menu.Trigger>
    <Menu.Positioner>
      <Menu.Content>
        <Menu.Root>
          <Menu.TriggerItem>JS Frameworks</Menu.TriggerItem>
          <Menu.Positioner>
            <Menu.Content>
              <Menu.Item value="react">React</Menu.Item>
              <Menu.Item value="solid">Solid</Menu.Item>
              <Menu.Item value="vue">Vue</Menu.Item>
            </Menu.Content>
          </Menu.Positioner>
        </Menu.Root>
        <Menu.Root>
          <Menu.TriggerItem>CSS Frameworks</Menu.TriggerItem>
          <Menu.Positioner>
            <Menu.Content>
              <Menu.Item value="panda">Panda</Menu.Item>
              <Menu.Item value="tailwind">Tailwind</Menu.Item>
            </Menu.Content>
          </Menu.Positioner>
        </Menu.Root>
      </Menu.Content>
    </Menu.Positioner>
  </Menu.Root>
</template>

Checkbox

To add a checkbox to a menu item, use the Menu.Checkbox component.

<script setup lang="ts">
import { Menu } from '@ark-ui/vue/menu'
import { ref } from 'vue'

const checked = ref(true)
</script>

<template>
  <Menu.Root>
    <Menu.Trigger>Open menu</Menu.Trigger>
    <Menu.Positioner>
      <Menu.Content>
        <Menu.CheckboxItem v-model:checked="checked" value="my-checkbox">
          <Menu.ItemIndicator>✅</Menu.ItemIndicator>
          <Menu.ItemText>Check me</Menu.ItemText>
        </Menu.CheckboxItem>
      </Menu.Content>
    </Menu.Positioner>
  </Menu.Root>
</template>

Radio Group

To group radio option items, use the Menu.RadioGroup component.

<script setup lang="ts">
import { Menu } from '@ark-ui/vue/menu'
import { ref } from 'vue'

const value = ref('React')
const items = ref(['React', 'Solid', 'Vue'])
</script>

<template>
  <Menu.Root>
    <Menu.Trigger>Open menu</Menu.Trigger>
    <Menu.Positioner>
      <Menu.Content>
        <Menu.RadioItemGroup v-model="value">
          <Menu.ItemGroupLabel>JS Frameworks</Menu.ItemGroupLabel>
          <Menu.RadioItem v-for="item in items" :key="item" :value="item">
            <Menu.ItemIndicator>✅</Menu.ItemIndicator>
            <Menu.ItemText>{{ item }}</Menu.ItemText>
          </Menu.RadioItem>
        </Menu.RadioItemGroup>
      </Menu.Content>
    </Menu.Positioner>
  </Menu.Root>
</template>

Using the Root Provider

The RootProvider component provides a context for the menu. It accepts the value of the useMenu hook. You can leverage it to access the component state and methods from outside the menu.

<script setup lang="ts">
import { Menu, useMenu } from '@ark-ui/vue/menu'

const menu = useMenu()
</script>

<template>
  <button @click="menu.api.value.setHighlightedValue('solid')">Highlight Solid</button>

  <Menu.Root>
    <Menu.Trigger>
      Open menu
      <Menu.Indicator>➡️</Menu.Indicator>
    </Menu.Trigger>
    <Menu.Positioner>
      <Menu.Content>
        <Menu.Item value="react">React</Menu.Item>
        <Menu.Item value="solid">Solid</Menu.Item>
        <Menu.Item value="vue">Vue</Menu.Item>
      </Menu.Content>
    </Menu.Positioner>
  </Menu.Root>
</template>

If you're using the RootProvider component, you don't need to use the Root component.

API Reference

Root

PropDefaultType
anchorPoint
Point

The positioning point for the menu. Can be set by the context menu trigger or the button trigger.

aria-label
string

The accessibility label for the menu

asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
closeOnSelecttrue
boolean

Whether to close the menu when an option is selected

compositetrue
boolean

Whether the menu is a composed with other composite widgets like a combobox or tabs

defaultOpen
boolean

The initial open state of the menu when it is first rendered. Use when you do not need to control its open state.

highlightedValue
string

The value of the highlighted menu item.

id
string

The unique identifier of the machine.

ids
Partial<{ trigger: string contextTrigger: string content: string groupLabel(id: string): string group(id: string): string positioner: string arrow: string }>

The ids of the elements in the menu. Useful for composition.

lazyMountfalse
boolean

Whether to enable lazy mounting

loopFocusfalse
boolean

Whether to loop the keyboard navigation.

open
boolean

Whether the menu is open

positioning
PositioningOptions

The options used to dynamically position the menu

typeaheadtrue
boolean

Whether the pressing printable characters should trigger typeahead navigation

unmountOnExitfalse
boolean

Whether to unmount on exit.

EmitEvent
escapeKeyDown
[event: KeyboardEvent]

Function called when the escape key is pressed

focusOutside
[event: FocusOutsideEvent]

Function called when the focus is moved outside the component

highlightChange
[details: HighlightChangeDetails]

Function called when the highlighted menu item changes.

interactOutside
[event: InteractOutsideEvent]

Function called when an interaction happens outside the component

openChange
[details: OpenChangeDetails]

Function called when the menu opens or closes

pointerDownOutside
[event: PointerDownOutsideEvent]

Function called when the pointer is pressed down outside the component

select
[details: SelectionDetails]

Function called when a menu item is selected.

update:open
[open: boolean]

Function called when the menu is opened or closed.

Arrow

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.

ArrowTip

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.

CheckboxItem

PropDefaultType
checked
boolean

Whether the option is checked

value
string

The value of the option

asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
closeOnSelect
boolean

Whether the menu should be closed when the option is selected.

disabled
boolean

Whether the menu item is disabled

valueText
string

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.

EmitEvent
update:checked
[value: boolean]

Content

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
Data AttributeValue
[data-scope]menu
[data-part]content
[data-state]"open" | "closed"
[data-placement]The placement of the content

ContextTrigger

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.

Indicator

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
Data AttributeValue
[data-scope]menu
[data-part]indicator
[data-state]"open" | "closed"

ItemGroupLabel

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.

ItemGroup

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
id
string

The `id` of the element that provides accessibility label to the option group

ItemIndicator

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
Data AttributeValue
[data-scope]menu
[data-part]item-indicator
[data-disabled]Present when disabled
[data-highlighted]Present when highlighted
[data-state]"checked" | "unchecked"

Item

PropDefaultType
value
string

The unique value of the menu item option.

asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
closeOnSelect
boolean

Whether the menu should be closed when the option is selected.

disabled
boolean

Whether the menu item is disabled

valueText
string

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.

Data AttributeValue
[data-scope]menu
[data-part]item
[data-disabled]Present when disabled
[data-highlighted]Present when highlighted
[data-valuetext]The human-readable value

ItemText

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
Data AttributeValue
[data-scope]menu
[data-part]item-text
[data-disabled]Present when disabled
[data-highlighted]Present when highlighted
[data-state]"checked" | "unchecked"

Positioner

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.

RadioItemGroup

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
id
string

modelValue
string

EmitEvent
update:modelValue
[value: string]

RadioItem

PropDefaultType
value
string

The value of the option

asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
closeOnSelect
boolean

Whether the menu should be closed when the option is selected.

disabled
boolean

Whether the menu item is disabled

valueText
string

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.

RootProvider

PropDefaultType
value
UseMenuReturn

asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
lazyMountfalse
boolean

Whether to enable lazy mounting

unmountOnExitfalse
boolean

Whether to unmount on exit.

Separator

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.

TriggerItem

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.

Trigger

PropDefaultType
asChild
boolean

Use the provided child element as the default rendered element, combining their props and behavior.

For more details, read our Composition guide.
Data AttributeValue
[data-scope]menu
[data-part]trigger
[data-placement]The placement of the trigger
[data-state]"open" | "closed"

Accessibility

Complies with the Menu WAI-ARIA design pattern.

Keyboard Support

KeyDescription
Space
Activates/Selects the highlighted item
Enter
Activates/Selects the highlighted item
ArrowDown
Highlights the next item in the menu
ArrowUp
Highlights the previous item in the menu
ArrowRightArrowLeft
When focus is on trigger, opens or closes the submenu depending on reading direction.
Esc
Closes the menu and moves focus to the trigger