# Menu

URL: https://ark-ui.com/docs/components/menu
Source: https://raw.githubusercontent.com/chakra-ui/ark/refs/heads/main/website/src/content/pages/components/menu.mdx

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

---

<ComponentPreview id="Menu" />

## Anatomy

<Anatomy id="menu" />

```tsx
<Menu.Root>
  <Menu.Trigger>
    <Menu.Indicator />
  </Menu.Trigger>
  <Menu.Positioner>
    <Menu.Content>
      <Menu.Arrow>
        <Menu.ArrowTip />
      </Menu.Arrow>
      <Menu.Item />
      <Menu.ItemGroup>
        <Menu.ItemGroupLabel />
        <Menu.Item />
      </Menu.ItemGroup>
      <Menu.Separator />
    </Menu.Content>
  </Menu.Positioner>
</Menu.Root>
```

## Examples

**Example: basic**

```ripple
import { Menu } from 'ark-ripple/menu';
import { ChevronDown } from 'lucide-ripple';
import styles from 'styles/menu.module.css';

export component Basic() {
  <Menu.Root>
    <Menu.Trigger class={styles.Trigger}>
      {'File'}
      <Menu.Indicator class={styles.Indicator}>
        <ChevronDown />
      </Menu.Indicator>
    </Menu.Trigger>
    <Menu.Positioner>
      <Menu.Content class={styles.Content}>
        <Menu.Item class={styles.Item} value="new-file">{'New File'}</Menu.Item>
        <Menu.Item class={styles.Item} value="open">{'Open...'}</Menu.Item>
        <Menu.Item class={styles.Item} value="save">{'Save'}</Menu.Item>
        <Menu.Item class={styles.Item} value="save-as">{'Save As...'}</Menu.Item>
      </Menu.Content>
    </Menu.Positioner>
  </Menu.Root>
}

```

### Item Selection

Use `onSelect` to handle item selection. The callback receives the item's `id`.

**Example: controlled**

```ripple
import { Menu } from 'ark-ripple/menu';
import { ChevronDown } from 'lucide-ripple';
import { track } from 'ripple';
import button from 'styles/button.module.css';
import styles from 'styles/menu.module.css';

export component Controlled() {
  let open = track(false);

  <div class="stack">
    <button
      type="button"
      class={button.Root}
      onclick={() => {
        @open = !@open;
      }}
    >
      {'Toggle'}
    </button>
    <Menu.Root
      {open}
      onOpenChange={(e) => {
        @open = e.open;
      }}
    >
      <Menu.Trigger class={styles.Trigger}>
        {'Actions'}
        <Menu.Indicator class={styles.Indicator}>
          <ChevronDown />
        </Menu.Indicator>
      </Menu.Trigger>
      <Menu.Positioner>
        <Menu.Content class={styles.Content}>
          <Menu.Item class={styles.Item} value="edit">{'Edit'}</Menu.Item>
          <Menu.Item class={styles.Item} value="duplicate">{'Duplicate'}</Menu.Item>
          <Menu.Item class={styles.Item} value="archive">{'Archive'}</Menu.Item>
          <Menu.Item class={styles.Item} value="delete">{'Delete'}</Menu.Item>
        </Menu.Content>
      </Menu.Positioner>
    </Menu.Root>
  </div>
}

```

### Root Provider

An alternative way to control the menu is to use the `RootProvider` component and the `useMenu` hook. This way you can
access the state and methods from outside the component.

**Example: root-provider**

```ripple
import { Menu, useMenu } from 'ark-ripple/menu';
import { ChevronDown } from 'lucide-ripple';
import button from 'styles/button.module.css';
import styles from 'styles/menu.module.css';

export component RootProvider() {
  const menu = useMenu();

  <div class="stack">
    <button class={button.Root} onclick={() => menu.@api.setHighlightedValue('copy')}>
      {'Highlight Copy'}
    </button>
    <Menu.RootProvider value={menu}>
      <Menu.Trigger class={styles.Trigger}>
        {'Edit'}
        <Menu.Indicator class={styles.Indicator}>
          <ChevronDown />
        </Menu.Indicator>
      </Menu.Trigger>
      <Menu.Positioner>
        <Menu.Content class={styles.Content}>
          <Menu.Item class={styles.Item} value="cut">{'Cut'}</Menu.Item>
          <Menu.Item class={styles.Item} value="copy">{'Copy'}</Menu.Item>
          <Menu.Item class={styles.Item} value="paste">{'Paste'}</Menu.Item>
          <Menu.Item class={styles.Item} value="delete">{'Delete'}</Menu.Item>
        </Menu.Content>
      </Menu.Positioner>
    </Menu.RootProvider>
  </div>
}

```

### Grouping

Use `Menu.ItemGroup` and `Menu.ItemGroupLabel` to organize related menu items.

**Example: group**

```ripple
import { Menu } from 'ark-ripple/menu';
import { ChevronDown } from 'lucide-ripple';
import styles from 'styles/menu.module.css';

export component Group() {
  <Menu.Root>
    <Menu.Trigger class={styles.Trigger}>
      {'Edit'}
      <Menu.Indicator class={styles.Indicator}>
        <ChevronDown />
      </Menu.Indicator>
    </Menu.Trigger>
    <Menu.Positioner>
      <Menu.Content class={styles.Content}>
        <Menu.ItemGroup class={styles.ItemGroup}>
          <Menu.ItemGroupLabel class={styles.ItemGroupLabel}>{'Clipboard'}</Menu.ItemGroupLabel>
          <Menu.Item class={styles.Item} value="cut">{'Cut'}</Menu.Item>
          <Menu.Item class={styles.Item} value="copy">{'Copy'}</Menu.Item>
          <Menu.Item class={styles.Item} value="paste">{'Paste'}</Menu.Item>
        </Menu.ItemGroup>
        <Menu.ItemGroup class={styles.ItemGroup}>
          <Menu.ItemGroupLabel class={styles.ItemGroupLabel}>{'Selection'}</Menu.ItemGroupLabel>
          <Menu.Item class={styles.Item} value="select-all">{'Select All'}</Menu.Item>
          <Menu.Item class={styles.Item} value="deselect">{'Deselect'}</Menu.Item>
        </Menu.ItemGroup>
      </Menu.Content>
    </Menu.Positioner>
  </Menu.Root>
}

```

### Links

To render menu items as links, use the `asChild` prop to replace the default element with an anchor tag.

**Example: links**

```ripple
import { Menu } from 'ark-ripple/menu';
import { ChevronDown } from 'lucide-ripple';
import styles from 'styles/menu.module.css';

export component Links() {
  <Menu.Root>
    <Menu.Trigger class={styles.Trigger}>
      {'Help'}
      <Menu.Indicator class={styles.Indicator}>
        <ChevronDown />
      </Menu.Indicator>
    </Menu.Trigger>
    <Menu.Positioner>
      <Menu.Content class={styles.Content}>
        <Menu.Item class={styles.Item} value="docs">
          component asChild({ propsFn }) {
            <a {...propsFn({ href: 'https://ark-ui.rip' })}>{'Documentation'}</a>
          }
        </Menu.Item>
        <Menu.Item class={styles.Item} value="github">
          component asChild({ propsFn }) {
            <a {...propsFn({ href: 'https://github.com/chakra-ui/ark' })}>{'GitHub'}</a>
          }
        </Menu.Item>
        <Menu.Separator class={styles.Separator} />
        <Menu.Item class={styles.Item} value="changelog">
          component asChild({ propsFn }) {
            <a {...propsFn({ href: 'https://github.com/chakra-ui/ark/releases' })}>{'Changelog'}</a>
          }
        </Menu.Item>
      </Menu.Content>
    </Menu.Positioner>
  </Menu.Root>
}

```

### Checkbox

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

**Example: checkbox-items**

```ripple
import { Menu } from 'ark-ripple/menu';
import { Check, ChevronDown } from 'lucide-ripple';
import { track } from 'ripple';
import styles from 'styles/menu.module.css';

export component CheckboxItems() {
  let showToolbar = track(true);
  let showStatusBar = track(false);

  <Menu.Root>
    <Menu.Trigger class={styles.Trigger}>
      {'View'}
      <Menu.Indicator class={styles.Indicator}>
        <ChevronDown />
      </Menu.Indicator>
    </Menu.Trigger>
    <Menu.Positioner>
      <Menu.Content class={styles.Content}>
        <Menu.CheckboxItem
          class={styles.CheckboxItem}
          checked={showToolbar}
          onCheckedChange={(v) => {
            @showToolbar = v;
          }}
          value="toolbar"
        >
          <Menu.ItemIndicator class={styles.ItemIndicator}>
            <Check />
          </Menu.ItemIndicator>
          <Menu.ItemText class={styles.ItemText}>{'Show Toolbar'}</Menu.ItemText>
        </Menu.CheckboxItem>
        <Menu.CheckboxItem
          class={styles.CheckboxItem}
          checked={showStatusBar}
          onCheckedChange={(v) => {
            @showStatusBar = v;
          }}
          value="status-bar"
        >
          <Menu.ItemIndicator class={styles.ItemIndicator}>
            <Check />
          </Menu.ItemIndicator>
          <Menu.ItemText class={styles.ItemText}>{'Show Status Bar'}</Menu.ItemText>
        </Menu.CheckboxItem>
      </Menu.Content>
    </Menu.Positioner>
  </Menu.Root>
}

```

### Radio Group

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

**Example: radio-items**

```ripple
import { Menu } from 'ark-ripple/menu';
import { Check, ChevronDown } from 'lucide-ripple';
import { track } from 'ripple';
import styles from 'styles/menu.module.css';

export component RadioItems() {
  let sortBy = track('date');

  <Menu.Root>
    <Menu.Trigger class={styles.Trigger}>
      {'Sort'}
      <Menu.Indicator class={styles.Indicator}>
        <ChevronDown />
      </Menu.Indicator>
    </Menu.Trigger>
    <Menu.Positioner>
      <Menu.Content class={styles.Content}>
        <Menu.RadioItemGroup
          class={styles.ItemGroup}
          value={sortBy}
          onValueChange={(e) => {
            @sortBy = e.value;
          }}
        >
          <Menu.ItemGroupLabel class={styles.ItemGroupLabel}>{'Sort By'}</Menu.ItemGroupLabel>
          <Menu.RadioItem class={styles.RadioItem} value="name">
            <Menu.ItemIndicator class={styles.ItemIndicator}>
              <Check />
            </Menu.ItemIndicator>
            <Menu.ItemText class={styles.ItemText}>{'Name'}</Menu.ItemText>
          </Menu.RadioItem>
          <Menu.RadioItem class={styles.RadioItem} value="date">
            <Menu.ItemIndicator class={styles.ItemIndicator}>
              <Check />
            </Menu.ItemIndicator>
            <Menu.ItemText class={styles.ItemText}>{'Date Modified'}</Menu.ItemText>
          </Menu.RadioItem>
          <Menu.RadioItem class={styles.RadioItem} value="size">
            <Menu.ItemIndicator class={styles.ItemIndicator}>
              <Check />
            </Menu.ItemIndicator>
            <Menu.ItemText class={styles.ItemText}>{'Size'}</Menu.ItemText>
          </Menu.RadioItem>
          <Menu.RadioItem class={styles.RadioItem} value="type">
            <Menu.ItemIndicator class={styles.ItemIndicator}>
              <Check />
            </Menu.ItemIndicator>
            <Menu.ItemText class={styles.ItemText}>{'Type'}</Menu.ItemText>
          </Menu.RadioItem>
        </Menu.RadioItemGroup>
      </Menu.Content>
    </Menu.Positioner>
  </Menu.Root>
}

```

### 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.

**Example: context**

```ripple
import { Menu } from 'ark-ripple/menu';
import styles from 'styles/menu.module.css';

export component Context() {
  <Menu.Root>
    <Menu.ContextTrigger class={styles.ContextTrigger}>{'Right click here'}</Menu.ContextTrigger>
    <Menu.Positioner>
      <Menu.Content class={styles.Content}>
        <Menu.Item class={styles.Item} value="cut">{'Cut'}</Menu.Item>
        <Menu.Item class={styles.Item} value="copy">{'Copy'}</Menu.Item>
        <Menu.Item class={styles.Item} value="paste">{'Paste'}</Menu.Item>
        <Menu.Separator class={styles.Separator} />
        <Menu.Item class={styles.Item} value="delete">{'Delete'}</Menu.Item>
      </Menu.Content>
    </Menu.Positioner>
  </Menu.Root>
}

```

### Nested

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

**Example: nested**

```ripple
import { Menu } from 'ark-ripple/menu';
import { ChevronDown } from 'lucide-ripple';
import styles from 'styles/menu.module.css';

export component Nested() {
  <Menu.Root>
    <Menu.Trigger class={styles.Trigger}>
      {'File'}
      <Menu.Indicator class={styles.Indicator}>
        <ChevronDown />
      </Menu.Indicator>
    </Menu.Trigger>
    <Menu.Positioner>
      <Menu.Content class={styles.Content}>
        <Menu.Item class={styles.Item} value="new">{'New File'}</Menu.Item>
        <Menu.Item class={styles.Item} value="open">{'Open...'}</Menu.Item>
        <Menu.Separator class={styles.Separator} />
        <Menu.Root>
          <Menu.TriggerItem class={styles.TriggerItem}>{'Share'}</Menu.TriggerItem>
          <Menu.Positioner>
            <Menu.Content class={styles.Content}>
              <Menu.Item class={styles.Item} value="email">{'Email'}</Menu.Item>
              <Menu.Item class={styles.Item} value="message">{'Message'}</Menu.Item>
              <Menu.Item class={styles.Item} value="airdrop">{'AirDrop'}</Menu.Item>
            </Menu.Content>
          </Menu.Positioner>
        </Menu.Root>
        <Menu.Root>
          <Menu.TriggerItem class={styles.TriggerItem}>{'Export'}</Menu.TriggerItem>
          <Menu.Positioner>
            <Menu.Content class={styles.Content}>
              <Menu.Item class={styles.Item} value="pdf">{'PDF'}</Menu.Item>
              <Menu.Item class={styles.Item} value="png">{'PNG'}</Menu.Item>
              <Menu.Item class={styles.Item} value="svg">{'SVG'}</Menu.Item>
            </Menu.Content>
          </Menu.Positioner>
        </Menu.Root>
        <Menu.Separator class={styles.Separator} />
        <Menu.Item class={styles.Item} value="print">{'Print...'}</Menu.Item>
      </Menu.Content>
    </Menu.Positioner>
  </Menu.Root>
}

```

### Menu in Dialog

When rendering a menu inside a dialog, use `lazyMount` and `unmountOnExit` to ensure proper cleanup when the dialog
closes.

**Example: menu-in-dialog**

```ripple
import { Dialog } from 'ark-ripple/dialog';
import { Menu } from 'ark-ripple/menu';
import { Portal } from 'ark-ripple/portal';
import { ChevronDown, X } from 'lucide-ripple';
import button from 'styles/button.module.css';
import dialog from 'styles/dialog.module.css';
import styles from 'styles/menu.module.css';

export component MenuInDialog() {
  <Dialog.Root>
    <Dialog.Trigger class={button.Root}>{'Open Dialog'}</Dialog.Trigger>
    <Portal>
      <Dialog.Backdrop class={dialog.Backdrop} />
      <Dialog.Positioner class={dialog.Positioner}>
        <Dialog.Content class={dialog.Content}>
          <Dialog.Title class={dialog.Title}>{'Settings'}</Dialog.Title>
          <Dialog.Description class={dialog.Description}>
            {'Configure your preferences below.'}
          </Dialog.Description>
          <Dialog.CloseTrigger class={dialog.CloseTrigger}>
            <X />
          </Dialog.CloseTrigger>
          <div class={dialog.Body}>
            <Menu.Root lazyMount unmountOnExit>
              <Menu.Trigger class={styles.Trigger}>
                {'Select theme'}
                <Menu.Indicator class={styles.Indicator}>
                  <ChevronDown />
                </Menu.Indicator>
              </Menu.Trigger>
              <Portal>
                <Menu.Positioner>
                  <Menu.Content class={styles.Content}>
                    <Menu.Arrow class={styles.Arrow}>
                      <Menu.ArrowTip class={styles.ArrowTip} />
                    </Menu.Arrow>
                    <Menu.Item class={styles.Item} value="light">{'Light'}</Menu.Item>
                    <Menu.Item class={styles.Item} value="dark">{'Dark'}</Menu.Item>
                    <Menu.Item class={styles.Item} value="system">{'System'}</Menu.Item>
                  </Menu.Content>
                </Menu.Positioner>
              </Portal>
            </Menu.Root>
          </div>
        </Dialog.Content>
      </Dialog.Positioner>
    </Portal>
  </Dialog.Root>
}

```

### Menu Item Dialog

Open a confirmation dialog from a menu item. This pattern is useful for destructive actions like delete that require
user confirmation.

**Example: menu-item-dialog**

```ripple
import { Dialog } from 'ark-ripple/dialog';
import { Menu } from 'ark-ripple/menu';
import { Portal } from 'ark-ripple/portal';
import { ChevronDown, X } from 'lucide-ripple';
import { track } from 'ripple';
import button from 'styles/button.module.css';
import dialog from 'styles/dialog.module.css';
import styles from 'styles/menu.module.css';

export component MenuItemDialog() {
  let dialogOpen = track(false);

  <Menu.Root>
    <Menu.Trigger class={styles.Trigger}>
      {'Actions'}
      <Menu.Indicator class={styles.Indicator}>
        <ChevronDown />
      </Menu.Indicator>
    </Menu.Trigger>
    <Portal>
      <Menu.Positioner>
        <Menu.Content class={styles.Content}>
          <Menu.Item class={styles.Item} value="edit">{'Edit'}</Menu.Item>
          <Menu.Item class={styles.Item} value="duplicate">{'Duplicate'}</Menu.Item>
          <Menu.Separator class={styles.Separator} />
          <Menu.Item
            class={styles.Item}
            value="delete"
            onSelect={() => {
              @dialogOpen = true;
            }}
          >
            {'Delete...'}
          </Menu.Item>
        </Menu.Content>
      </Menu.Positioner>
    </Portal>
  </Menu.Root>

  <Dialog.Root
    open={dialogOpen}
    onOpenChange={(e) => {
      @dialogOpen = e.open;
    }}
    role="alertdialog"
  >
    <Portal>
      <Dialog.Backdrop class={dialog.Backdrop} />
      <Dialog.Positioner class={dialog.Positioner}>
        <Dialog.Content class={dialog.Content}>
          <Dialog.Title class={dialog.Title}>{'Confirm Delete'}</Dialog.Title>
          <Dialog.Description class={dialog.Description}>
            {'Are you sure you want to delete this item? This action cannot be undone.'}
          </Dialog.Description>
          <Dialog.CloseTrigger class={dialog.CloseTrigger}>
            <X />
          </Dialog.CloseTrigger>
          <div class={dialog.Actions}>
            <button
              class={button.Root}
              onclick={() => {
                @dialogOpen = false;
              }}
            >
              {'Cancel'}
            </button>
            <button
              class={button.Root}
              data-variant="solid"
              onclick={() => {
                @dialogOpen = false;
              }}
            >
              {'Delete'}
            </button>
          </div>
        </Dialog.Content>
      </Dialog.Positioner>
    </Portal>
  </Dialog.Root>
}

```

## Guides

### Custom IDs

Ark UI autogenerates ids for menu items internally. Passing a custom `id` prop breaks the internal `getElementById`
functionality used by the component.

```tsx
// ❌ Don't do this
<Menu.Item id="custom-id" value="custom-value">
  Custom Item
</Menu.Item>

// ✅ Do this
<Menu.Item value="custom-value">
  Custom Item
</Menu.Item>
```

### Links

To render a menu item as a link, render the link as the menu item itself using `asChild`, not as a child of the
menu item.

> This pattern ensures the link element receives the correct ARIA attributes and keyboard interactions from the menu
> item.

Here's an example of a reusable `MenuItemLink` component:

```tsx
interface MenuItemLinkProps extends Menu.ItemProps {
  href?: string
  target?: string
}

export component MenuItemLink({ href, target, children, ...rest }: MenuItemLinkProps) {
  return (
    <Menu.Item>
      component asChild({ propsFn }) {
        <a {...propsFn({...rest, href, target })}>
          <@children />
        </a>
      }
    </Menu.Item>
  )
}
```

## API Reference

### Props

**Component API Reference**

**Root Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `anchorPoint` | `Point` | No | The positioning point for the menu. Can be set by the context menu trigger or the button trigger. |
| `aria-label` | `string` | No | The accessibility label for the menu |
| `closeOnSelect` | `boolean` | No | Whether to close the menu when an option is selected |
| `composite` | `boolean` | No | Whether the menu is a composed with other composite widgets like a combobox or tabs |
| `defaultHighlightedValue` | `string` | No | 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. |
| `defaultOpen` | `boolean` | No | The initial open state of the menu when rendered.
Use when you don't need to control the open state of the menu. |
| `highlightedValue` | `string` | No | The controlled highlighted value of the menu item. |
| `id` | `string` | No | 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
}>` | No | The ids of the elements in the menu. Useful for composition. |
| `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame |
| `lazyMount` | `boolean` | No | Whether to enable lazy mounting |
| `loopFocus` | `boolean` | No | Whether to loop the keyboard navigation. |
| `navigate` | `(details: NavigateDetails) => void` | No | Function to navigate to the selected item if it's an anchor element |
| `onEscapeKeyDown` | `(event: KeyboardEvent) => void` | No | Function called when the escape key is pressed |
| `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state |
| `onFocusOutside` | `(event: FocusOutsideEvent) => void` | No | Function called when the focus is moved outside the component |
| `onHighlightChange` | `(details: HighlightChangeDetails) => void` | No | Function called when the highlighted menu item changes. |
| `onInteractOutside` | `(event: InteractOutsideEvent) => void` | No | Function called when an interaction happens outside the component |
| `onOpenChange` | `(details: OpenChangeDetails) => void` | No | Function called when the menu opens or closes |
| `onPointerDownOutside` | `(event: PointerDownOutsideEvent) => void` | No | Function called when the pointer is pressed down outside the component |
| `onRequestDismiss` | `(event: LayerDismissEvent) => void` | No | Function called when this layer is closed due to a parent layer being closed |
| `onSelect` | `(details: SelectionDetails) => void` | No | Function called when a menu item is selected. |
| `open` | `boolean` | No | The controlled open state of the menu |
| `positioning` | `PositioningOptions` | No | The options used to dynamically position the menu |
| `present` | `boolean` | No | Whether the node is present (controlled by the user) |
| `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. |
| `typeahead` | `boolean` | No | Whether the pressing printable characters should trigger typeahead navigation |
| `unmountOnExit` | `boolean` | No | Whether to unmount on exit. |


**Arrow Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Arrow CSS Variables:**

| Variable | Description |
|----------|-------------|
| `--arrow-size` | The size of the arrow |
| `--arrow-size-half` | Half the size of the arrow |
| `--arrow-background` | Use this variable to style the arrow background |
| `--arrow-offset` | The offset position of the arrow |


**ArrowTip Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**CheckboxItem Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `checked` | `boolean` | Yes | Whether the option is checked |
| `value` | `string` | Yes | The value of the option |
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `closeOnSelect` | `boolean` | No | Whether the menu should be closed when the option is selected. |
| `disabled` | `boolean` | No | Whether the menu item is disabled |
| `onCheckedChange` | `(checked: boolean) => void` | No | Function called when the option state is changed |
| `valueText` | `string` | No | 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. |


**Content Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Content Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | menu |
| `[data-part]` | content |
| `[data-state]` | "open" | "closed" |
| `[data-nested]` | menu |
| `[data-has-nested]` | menu |
| `[data-placement]` | The placement of the content |


**Content CSS Variables:**

| Variable | Description |
|----------|-------------|
| `--layer-index` | The index of the dismissable in the layer stack |
| `--nested-layer-count` | The number of nested menus |


**ContextTrigger Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**ContextTrigger Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | menu |
| `[data-part]` | context-trigger |
| `[data-state]` | "open" | "closed" |


**Indicator Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Indicator Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | menu |
| `[data-part]` | indicator |
| `[data-state]` | "open" | "closed" |


**ItemGroupLabel Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**ItemGroup Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**ItemIndicator Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**ItemIndicator Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | menu |
| `[data-part]` | item-indicator |
| `[data-disabled]` | Present when disabled |
| `[data-highlighted]` | Present when highlighted |
| `[data-state]` | "checked" |


**Item Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `value` | `string` | Yes | The unique value of the menu item option. |
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `closeOnSelect` | `boolean` | No | Whether the menu should be closed when the option is selected. |
| `disabled` | `boolean` | No | Whether the menu item is disabled |
| `onSelect` | `VoidFunction` | No | The function to call when the item is selected |
| `valueText` | `string` | No | 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. |


**Item Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | menu |
| `[data-part]` | item |
| `[data-disabled]` | Present when disabled |
| `[data-highlighted]` | Present when highlighted |
| `[data-value]` | The value of the item |
| `[data-valuetext]` | The human-readable value |


**ItemText Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**ItemText Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | menu |
| `[data-part]` | item-text |
| `[data-disabled]` | Present when disabled |
| `[data-highlighted]` | Present when highlighted |
| `[data-state]` | "checked" |


**Positioner Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Positioner CSS Variables:**

| Variable | Description |
|----------|-------------|
| `--reference-width` | The width of the reference element |
| `--reference-height` | The height of the root |
| `--available-width` | The available width in viewport |
| `--available-height` | The available height in viewport |
| `--x` | The x position for transform |
| `--y` | The y position for transform |
| `--z-index` | The z-index value |
| `--transform-origin` | The transform origin for animations |


**RadioItemGroup Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `onValueChange` | `(e: ValueChangeDetails) => void` | No |  |
| `value` | `string` | No |  |


**RadioItem Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `value` | `string` | Yes | The value of the option |
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |
| `closeOnSelect` | `boolean` | No | Whether the menu should be closed when the option is selected. |
| `disabled` | `boolean` | No | Whether the menu item is disabled |
| `valueText` | `string` | No | 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 Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `value` | `UseMenuReturn` | Yes |  |
| `immediate` | `boolean` | No | Whether to synchronize the present change immediately or defer it to the next frame |
| `lazyMount` | `boolean` | No | Whether to enable lazy mounting |
| `onExitComplete` | `VoidFunction` | No | Function called when the animation ends in the closed state |
| `present` | `boolean` | No | Whether the node is present (controlled by the user) |
| `skipAnimationOnMount` | `boolean` | No | Whether to allow the initial presence animation. |
| `unmountOnExit` | `boolean` | No | Whether to unmount on exit. |


**Separator Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**TriggerItem Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Trigger Props:**

| Prop | Type | Required | Description |
|------|------|----------|-------------|
| `asChild` | `boolean` | No | Use the provided child element as the default rendered element, combining their props and behavior. |


**Trigger Data Attributes:**

| Attribute | Value |
|-----------|-------|
| `[data-scope]` | menu |
| `[data-part]` | trigger |
| `[data-placement]` | The placement of the trigger |
| `[data-controls]` |  |
| `[data-state]` | "open" | "closed" |


### Context

**API:**

| Property | Type | Description |
|----------|------|-------------|
| `open` | `boolean` | Whether the menu is open |
| `setOpen` | `(open: boolean) => void` | Function to open or close the menu |
| `highlightedValue` | `string` | The id of the currently highlighted menuitem |
| `setHighlightedValue` | `(value: string) => void` | Function to set the highlighted menuitem |
| `setParent` | `(parent: ParentMenuService) => void` | Function to register a parent menu. This is used for submenus |
| `setChild` | `(child: ChildMenuService) => void` | Function to register a child menu. This is used for submenus |
| `reposition` | `(options?: Partial<PositioningOptions>) => void` | Function to reposition the popover |
| `getOptionItemState` | `(props: OptionItemProps) => OptionItemState` | Returns the state of the option item |
| `getItemState` | `(props: ItemProps) => ItemState` | Returns the state of the menu item |
| `addItemListener` | `(props: ItemListenerProps) => VoidFunction` | Setup the custom event listener for item selection event |


## Accessibility

Complies with the [Menu WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/menubar/).

### Keyboard Support

<KeyBindingsTable id="menu" />