---
title: "Dropdown Menu"
description: "Displays a menu to the user—such as a set of actions or functions—triggered by a button."
canonical_url: "https://vinicunca.dev/akar/components/dropdown-menu"
---
# Dropdown Menu

> Displays a menu to the user—such as a set of actions or functions—triggered by a button.

## DropdownMenu

```vue [index.vue]
<script setup lang="ts">
import {
  DropdownMenuArrow,
  DropdownMenuCheckboxItem,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuItemIndicator,
  DropdownMenuLabel,
  DropdownMenuPortal,
  DropdownMenuRadioGroup,
  DropdownMenuRadioItem,
  DropdownMenuRoot,
  DropdownMenuSeparator,
  DropdownMenuSub,
  DropdownMenuSubContent,
  DropdownMenuSubTrigger,
  DropdownMenuTrigger,
} from 'akar'
import { ref } from 'vue'
import './styles.css'

const toggleState = ref(false)
const checkboxOne = ref(false)
const checkboxTwo = ref(false)
const person = ref('pedro')

function handleSelect() {
  // eslint-disable-next-line no-alert
  alert('hello!')
}
</script>

<template>
  <div class="akar-demo akar-demo-DropdownMenu">
    <DropdownMenuRoot v-model:open="toggleState">
        <DropdownMenuTrigger
          class="IconButton"
          aria-label="Customise options"
        >
          <PIcon name="i-lucide-menu" />
        </DropdownMenuTrigger>

        <DropdownMenuPortal>
          <DropdownMenuContent
            class="DropdownMenuContent"
            :side-offset="5"
          >
            <DropdownMenuItem
              value="New Tab"
              class="DropdownMenuItem"
              @select="handleSelect"
            >
              New Tab
              <div
                class="RightSlot"
              >
                ⌘+T
              </div>
            </DropdownMenuItem>
            <DropdownMenuSub>
              <DropdownMenuSubTrigger
                value="more toolsz"
                class="DropdownMenuSubTrigger"
              >
                More Tools
                <div
                  class="RightSlot"
                >
                  <PIcon name="i-lucide-chevron-right" />
                </div>
              </DropdownMenuSubTrigger>
              <DropdownMenuPortal>
                <DropdownMenuSubContent
                  class="DropdownMenuContent"
                  :side-offset="2"
                  :align-offset="-5"
                >
                  <DropdownMenuItem
                    class="DropdownMenuItem"
                  >
                    Save Page As…
                    <div
                      class="RightSlot"
                    >
                      ⌘+S
                    </div>
                  </DropdownMenuItem>
                  <DropdownMenuItem
                    class="DropdownMenuItem"
                  >
                    Create Shortcut…
                  </DropdownMenuItem>
                  <DropdownMenuItem
                    class="DropdownMenuItem"
                  >
                    Name Window…
                  </DropdownMenuItem>
                  <DropdownMenuSeparator class="DropdownMenuSeparator" />
                  <DropdownMenuItem
                    class="DropdownMenuItem"
                  >
                    Developer Tools
                  </DropdownMenuItem>
                </DropdownMenuSubContent>
              </DropdownMenuPortal>
            </DropdownMenuSub>
            <DropdownMenuItem
              value="New Window"
              class="DropdownMenuItem"
            >
              New Window
              <div
                class="RightSlot"
              >
                ⌘+N
              </div>
            </DropdownMenuItem>
            <DropdownMenuItem
              value="New Private Window"
              class="DropdownMenuItem"
              disabled
            >
              New Private Window
              <div
                class="RightSlot"
              >
                ⇧+⌘+N
              </div>
            </DropdownMenuItem>
            <DropdownMenuSub>
              <DropdownMenuSubTrigger
                value="more tools"
                class="DropdownMenuSubTrigger"
              >
                More Tools
                <div
                  class="RightSlot"
                >
                  <PIcon name="i-lucide-chevron-right" />
                </div>
              </DropdownMenuSubTrigger>
              <DropdownMenuPortal>
                <DropdownMenuSubContent
                  class="DropdownMenuContent"
                  :side-offset="2"
                  :align-offset="-5"
                >
                  <DropdownMenuItem
                    class="DropdownMenuItem"
                  >
                    Save Page As…
                    <div
                      class="RightSlot"
                    >
                      ⌘+S
                    </div>
                  </DropdownMenuItem>
                  <DropdownMenuItem
                    class="DropdownMenuItem"
                  >
                    Create Shortcut…
                  </DropdownMenuItem>
                  <DropdownMenuItem
                    class="DropdownMenuItem"
                  >
                    Name Window…
                  </DropdownMenuItem>
                  <DropdownMenuSeparator class="DropdownMenuSeparator" />
                  <DropdownMenuItem
                    class="DropdownMenuItem"
                  >
                    Developer Tools
                  </DropdownMenuItem>
                  <DropdownMenuSub>
                    <DropdownMenuSubTrigger
                      value="more toolsz"
                      class="DropdownMenuSubTrigger"
                    >
                      More Tools
                      <div
                        class="RightSlot"
                      >
                        <PIcon name="i-lucide-chevron-right" />
                      </div>
                    </DropdownMenuSubTrigger>
                    <DropdownMenuPortal>
                      <DropdownMenuSubContent
                        class="DropdownMenuContent"
                        :side-offset="2"
                        :align-offset="-5"
                      >
                        <DropdownMenuItem
                          class="DropdownMenuItem"
                        >
                          Save Page As…
                          <div
                            class="RightSlot"
                          >
                            ⌘+S
                          </div>
                        </DropdownMenuItem>
                        <DropdownMenuItem
                          class="DropdownMenuItem"
                        >
                          Create Shortcut…
                        </DropdownMenuItem>
                        <DropdownMenuItem
                          class="DropdownMenuItem"
                        >
                          Name Window…
                        </DropdownMenuItem>
                        <DropdownMenuSeparator class="DropdownMenuSeparator" />
                        <DropdownMenuItem
                          class="DropdownMenuItem"
                        >
                          Developer Tools
                        </DropdownMenuItem>
                        <DropdownMenuSub>
                          <DropdownMenuSubTrigger
                            value="more toolsz"
                            class="DropdownMenuSubTrigger"
                          >
                            More Tools
                            <div
                              class="RightSlot"
                            >
                              <PIcon name="i-lucide-chevron-right" />
                            </div>
                          </DropdownMenuSubTrigger>
                          <DropdownMenuPortal>
                            <DropdownMenuSubContent
                              class="DropdownMenuContent"
                              :side-offset="2"
                              :align-offset="-5"
                            >
                              <DropdownMenuItem
                                class="DropdownMenuItem"
                              >
                                Save Page As…
                                <div
                                  class="RightSlot"
                                >
                                  ⌘+S
                                </div>
                              </DropdownMenuItem>
                              <DropdownMenuItem
                                class="DropdownMenuItem"
                              >
                                Create Shortcut…
                              </DropdownMenuItem>
                              <DropdownMenuItem
                                class="DropdownMenuItem"
                              >
                                Name Window…
                              </DropdownMenuItem>
                              <DropdownMenuSeparator class="DropdownMenuSeparator" />
                              <DropdownMenuItem
                                class="DropdownMenuItem"
                              >
                                Developer Tools
                              </DropdownMenuItem>
                            </DropdownMenuSubContent>
                          </DropdownMenuPortal>
                        </DropdownMenuSub>
                      </DropdownMenuSubContent>
                    </DropdownMenuPortal>
                  </DropdownMenuSub>
                  <DropdownMenuItem
                    class="DropdownMenuItem"
                  >
                    Developer Tools
                  </DropdownMenuItem>
                </DropdownMenuSubContent>
              </DropdownMenuPortal>
            </DropdownMenuSub>
            <DropdownMenuSeparator class="DropdownMenuSeparator" />
            <DropdownMenuCheckboxItem
              v-model="checkboxOne"
              class="DropdownMenuItem"
            >
              <DropdownMenuItemIndicator class="DropdownMenuItemIndicator">
                <PIcon name="i-lucide-check" />
              </DropdownMenuItemIndicator>
              Show Bookmarks
              <div
                class="RightSlot"
              >
                ⌘+B
              </div>
            </DropdownMenuCheckboxItem>
            <DropdownMenuCheckboxItem
              v-model="checkboxTwo"
              class="DropdownMenuItem"
            >
              <DropdownMenuItemIndicator class="DropdownMenuItemIndicator">
                <PIcon name="i-lucide-check" />
              </DropdownMenuItemIndicator>
              Show Full URLs
            </DropdownMenuCheckboxItem>
            <DropdownMenuSeparator class="DropdownMenuSeparator" />

            <DropdownMenuLabel class="DropdownMenuLabel">
              People
            </DropdownMenuLabel>
            <DropdownMenuRadioGroup v-model="person">
              <DropdownMenuRadioItem
                class="DropdownMenuItem"
                value="pedro"
              >
                <DropdownMenuItemIndicator class="DropdownMenuItemIndicator">
                  <PIcon name="i-lucide-circle" />
                </DropdownMenuItemIndicator>
                Pedro Duarte
              </DropdownMenuRadioItem>
              <DropdownMenuRadioItem
                class="DropdownMenuItem"
                value="colm"
              >
                <DropdownMenuItemIndicator class="DropdownMenuItemIndicator">
                  <PIcon name="i-lucide-circle" />
                </DropdownMenuItemIndicator>
                Colm Tuite
              </DropdownMenuRadioItem>
            </DropdownMenuRadioGroup>
            <DropdownMenuArrow class="DropdownMenuArrow" />
          </DropdownMenuContent>
        </DropdownMenuPortal>
      </DropdownMenuRoot>
  </div>
</template>
```

```css [styles.css]
@import '../_colors/black-alpha.css';
@import '../_colors/mauve.css';
@import '../_colors/grass.css';

@scope (.akar-demo-DropdownMenu) {
/* reset */
button {
  all: unset;
}

.DropdownMenuContent,
.DropdownMenuSubContent {
  min-width: 220px;
  background-color: white;
  border-radius: 6px;
  padding: 5px;
  box-shadow: 0px 10px 38px -10px rgba(22, 23, 24, 0.35), 0px 10px 20px -15px rgba(22, 23, 24, 0.2);
  animation-duration: 400ms;
  animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
  will-change: transform, opacity;
}
.DropdownMenuContent[data-side='top'],
.DropdownMenuSubContent[data-side='top'] {
  animation-name: slideDownAndFade;
}
.DropdownMenuContent[data-side='right'],
.DropdownMenuSubContent[data-side='right'] {
  animation-name: slideLeftAndFade;
}
.DropdownMenuContent[data-side='bottom'],
.DropdownMenuSubContent[data-side='bottom'] {
  animation-name: slideUpAndFade;
}
.DropdownMenuContent[data-side='left'],
.DropdownMenuSubContent[data-side='left'] {
  animation-name: slideRightAndFade;
}

.DropdownMenuItem,
.DropdownMenuCheckboxItem,
.DropdownMenuRadioItem,
.DropdownMenuSubTrigger {
  font-size: 13px;
  line-height: 1;
  color: var(--grass-11);
  border-radius: 3px;
  display: flex;
  align-items: center;
  height: 25px;
  padding: 0 5px;
  position: relative;
  padding-left: 25px;
  user-select: none;
  outline: none;
}
.DropdownMenuSubTrigger[data-state='open'] {
  background-color: var(--grass-4);
  color: var(--grass-11);
}
.DropdownMenuItem[data-disabled],
.DropdownMenuCheckboxItem[data-disabled],
.DropdownMenuRadioItem[data-disabled],
.DropdownMenuSubTrigger[data-disabled] {
  color: var(--mauve-8);
  pointer-events: none;
}
.DropdownMenuItem[data-highlighted],
.DropdownMenuCheckboxItem[data-highlighted],
.DropdownMenuRadioItem[data-highlighted],
.DropdownMenuSubTrigger[data-highlighted] {
  background-color: var(--grass-9);
  color: var(--grass-1);
}

.DropdownMenuLabel {
  padding-left: 25px;
  font-size: 12px;
  line-height: 25px;
  color: var(--mauve-11);
}

.DropdownMenuSeparator {
  height: 1px;
  background-color: var(--grass-6);
  margin: 5px;
}

.DropdownMenuItemIndicator {
  position: absolute;
  left: 0;
  width: 25px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

.DropdownMenuArrow {
  fill: white;
}

.IconButton {
  font-family: inherit;
  border-radius: 100%;
  height: 35px;
  width: 35px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--grass-11);
  background-color: white;
  box-shadow: 0 2px 10px var(--black-a7);
}
.IconButton:hover {
  background-color: var(--grass-3);
}
.IconButton:focus {
  box-shadow: 0 0 0 2px black;
}

.RightSlot {
  margin-left: auto;
  padding-left: 20px;
  color: var(--mauve-11);
}
[data-highlighted] > .RightSlot {
  color: white;
}
[data-disabled] .RightSlot {
  color: var(--mauve-8);
}

@keyframes slideUpAndFade {
  from {
    opacity: 0;
    transform: translateY(2px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes slideRightAndFade {
  from {
    opacity: 0;
    transform: translateX(-2px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}

@keyframes slideDownAndFade {
  from {
    opacity: 0;
    transform: translateY(-2px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes slideLeftAndFade {
  from {
    opacity: 0;
    transform: translateX(2px);
  }
  to {
    opacity: 1;
    transform: translateX(0);
  }
}
}
```

## Features

- Can be controlled or uncontrolled.
- Supports submenus with configurable reading direction.
- Supports items, labels, groups of items.
- Supports checkable items (single or multiple) with optional indeterminate state.
- Supports modal and non-modal modes.
- Customize side, alignment, offsets, collision handling.
- Optionally render a pointing arrow.
- Focus is fully managed.
- Full keyboard navigation.
- Typeahead support.
- Dismissing and layering behavior is highly customizable.

## Installation

Install the component from your command line.

```bash [pnpm]
pnpm add akar
```

```bash [yarn]
yarn add akar
```

```bash [npm]
npm install akar
```

```bash [bun]
bun add akar
```

## Anatomy

Import all parts and piece them together.

```vue
<script setup lang="ts">
import {
  DropdownMenuArrow,
  DropdownMenuCheckboxItem,
  DropdownMenuContent,
  DropdownMenuFilter,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuItemIndicator,
  DropdownMenuLabel,
  DropdownMenuPortal,
  DropdownMenuRadioGroup,
  DropdownMenuRadioItem,
  DropdownMenuRoot,
  DropdownMenuSeparator,
  DropdownMenuSub,
  DropdownMenuSubContent,
  DropdownMenuSubTrigger,
  DropdownMenuTrigger,
} from 'akar';
</script>

<template>
  <DropdownMenuRoot>
    <DropdownMenuTrigger />

    <DropdownMenuPortal>
      <DropdownMenuContent>
        <DropdownMenuFilter />
        <DropdownMenuLabel />
        <DropdownMenuItem />

        <DropdownMenuGroup>
          <DropdownMenuItem />
        </DropdownMenuGroup>

        <DropdownMenuCheckboxItem>
          <DropdownMenuItemIndicator />
        </DropdownMenuCheckboxItem>

        <DropdownMenuRadioGroup>
          <DropdownMenuRadioItem>
            <DropdownMenuItemIndicator />
          </DropdownMenuRadioItem>
        </DropdownMenuRadioGroup>

        <DropdownMenuSub>
          <DropdownMenuSubTrigger />
          <DropdownMenuPortal>
            <DropdownMenuSubContent />
          </DropdownMenuPortal>
        </DropdownMenuSub>

        <DropdownMenuSeparator />
        <DropdownMenuArrow />
      </DropdownMenuContent>
    </DropdownMenuPortal>
  </DropdownMenuRoot>
</template>
```

## API Reference

### Root

Contains all the parts of a dropdown menu.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `defaultOpen` |  | `boolean` | The open state of the dropdown menu when it is initially rendered. Use when you do not need to control its open state. |
| `dir` |  | `"ltr" \| "rtl"` | The reading direction of the combobox when applicable.<br><br>If omitted, inherits globally from `ConfigProvider` or assumes LTR (left-to-right) reading mode. |
| `modal` | `true` | `boolean` | The modality of the dropdown menu.<br><br>When set to `true`, interaction with outside elements will be disabled and only menu content will be visible to screen readers. |
| `open` |  | `boolean` | The controlled open state of the menu. Can be used as `v-model:open`. |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `update:open` | `payload: boolean` |  |

**Slots**

| Slot | Payload | Description |
| --- | --- | --- |
| `open` | `boolean` | Current open state |

[DropdownMenuRoot.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuRoot.vue)

### Trigger

The button that toggles the dropdown menu. By default, the `DropdownMenuContent` will position itself against the trigger.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"button"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `disabled` |  | `boolean` | When `true`, prevents the user from interacting with item |

[DropdownMenuTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuTrigger.vue)

| Data attribute | Value |
| --- | --- |
| `[data-state]` | "open" \\| "closed" |
| `[data-disabled]` | Present when disabled |

### Portal

When used, portals the content part into the `body`.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `defer` |  | `boolean` | Defer the resolving of a Teleport target until other parts of the<br>application have mounted (requires Vue 3.5.0+)<br><br>[reference](https://vuejs.org/guide/built-ins/teleport.html#deferred-teleport) |
| `disabled` |  | `boolean` | Disable teleport and render the component inline<br><br>[reference](https://vuejs.org/guide/built-ins/teleport.html#disabling-teleport) |
| `forceMount` |  | `boolean` | Used to force mounting when more control is needed. Useful when<br>controlling animation with Vue animation libraries. |
| `to` |  | `string \| HTMLElement` | Vue native teleport component prop `:to`<br><br>[reference](https://vuejs.org/guide/built-ins/teleport.html#basic-usage) |

[DropdownMenuPortal.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuPortal.vue)

### Content

The component that pops out when the dropdown menu is open.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `align` | `"center"` | `"start" \| "center" \| "end"` | The preferred alignment against the trigger.<br>May change when collisions occur. |
| `alignFlip` | `true` | `boolean` | Flip alignment when colliding with boundary.<br>May only occur when `prioritizePosition` is true. |
| `alignOffset` | `0` | `number` | An offset in pixels from the `start` or `end` alignment options. |
| `arrowPadding` | `0` | `number` | The padding between the arrow and the edges of the content.<br>If your content has border-radius, this will prevent it from<br>overflowing the corners. |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `avoidCollisions` | `true` | `boolean` | When `true`, overrides the side and align preferences<br>to prevent collisions with boundary edges. |
| `collisionBoundary` | `[]` | `Element \| (Element \| null)[] \| null` | The element used as the collision boundary. By default<br>this is the viewport, though you can provide additional<br>element(s) to be included in this check. |
| `collisionPadding` | `0` | `number \| Partial<Record<"top" \| "right" \| "bottom" \| "left", number>>` | The distance in pixels from the boundary edges where collision<br>detection should occur. Accepts a number (same for all sides),<br>or a partial padding object, for example: { top: 20, left: 20 }. |
| `disableUpdateOnLayoutShift` | `false` | `boolean` | Whether to disable the update position for the content when the layout shifted. |
| `forceMount` |  | `boolean` | Used to force mounting when more control is needed. Useful when<br>controlling animation with Vue animation libraries. |
| `hideShiftedArrow` | `true` | `boolean` | When `true`, hides the arrow when it cannot be centered<br>to the reference element. |
| `hideWhenDetached` | `false` | `boolean` | Whether to hide the content when the trigger becomes fully occluded. |
| `loop` | `false` | `boolean` | When `true`, keyboard navigation will loop from last item to first, and vice versa. |
| `memoDependencies` |  | `unknown[]` | Reactive dependencies that should invalidate the memoized content subtree. |
| `positionStrategy` |  | `"fixed" \| "absolute"` | The type of CSS position property to use. |
| `prioritizePosition` | `false` | `boolean` | Force content to be position within the viewport.<br><br>Might overlap the reference element, which may not be desired. |
| `reference` |  | `ReferenceElement` | The custom element or virtual element that will be set as the reference<br>to position the floating element.<br><br>If provided, it will replace the default anchor element. |
| `side` | `"bottom"` | `"top" \| "right" \| "bottom" \| "left"` | The preferred side of the trigger to render against when open.<br>Will be reversed when collisions occur and avoidCollisions<br>is enabled. |
| `sideFlip` | `true` | `boolean` | Flip to the opposite side when colliding with boundary. |
| `sideOffset` | `0` | `number` | The distance in pixels from the trigger. |
| `sticky` | `"partial"` | `"partial" \| "always"` | The sticky behavior on the align axis. `partial` will keep the<br>content in the boundary as long as the trigger is at least partially<br>in the boundary whilst "always" will keep the content in the boundary<br>regardless. |
| `updatePositionStrategy` | `'optimized'` | `"always" \| "optimized"` | Strategy to update the position of the floating element on every animation frame. |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `closeAutoFocus` | `event: Event` | Event handler called when auto-focusing on close.<br>Can be prevented. |
| `escapeKeyDown` | `event: KeyboardEvent` | Event handler called when the escape key is down.<br>Can be prevented. |
| `focusOutside` | `event: FocusOutsideEvent` | Event handler called when the focus moves outside of the `DismissableLayer`.<br>Can be prevented. |
| `interactOutside` | `event: PointerDownOutsideEvent \| FocusOutsideEvent` | Event handler called when an interaction happens outside the `DismissableLayer`.<br>Specifically, when a `pointerdown` event happens outside or focus moves outside of it.<br>Can be prevented. |
| `openAutoFocus` | `event: Event` |  |
| `pointerDownOutside` | `event: PointerDownOutsideEvent` | Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`.<br>Can be prevented. |

[DropdownMenuContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuContent.vue)

| Data attribute | Value |
| --- | --- |
| `[data-state]` | "open" \\| "closed" |
| `[data-side]` | "left" \\| "right" \\| "bottom" \\| "top" |
| `[data-align]` | "start" \\| "end" \\| "center" |
| `[data-orientation]` | "vertical" \\| "horizontal" |

| CSS variable | Description |
| --- | --- |
| `--akar-dropdown-menu-content-transform-origin` | The `transform-origin` computed from the content and arrow positions/offsets |
| `--akar-dropdown-menu-content-available-width` | The remaining width between the trigger and the boundary edge |
| `--akar-dropdown-menu-content-available-height` | The remaining height between the trigger and the boundary edge |
| `--akar-dropdown-menu-trigger-width` | The width of the trigger |
| `--akar-dropdown-menu-trigger-height` | The height of the trigger |

### Filter

An optional search input inside `DropdownMenuContent` or `DropdownMenuSubContent`. It integrates text input with the menu's keyboard navigation.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"input"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `autoFocus` |  | `boolean` | Focus on element when mounted. |
| `disabled` |  | `boolean` | When `true`, prevents the user from interacting with the filter input |
| `modelValue` |  | `string` | The controlled value of the filter. Can be binded with v-model. |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `update:modelValue` | `string` |  |

**Slots**

| Slot | Payload | Description |
| --- | --- | --- |
| `modelValue` | `string` | Current input values |

[DropdownMenuFilter.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuFilter.vue)

| Data attribute | Value |
| --- | --- |
| `[data-disabled]` | Present when disabled |

### Arrow

An optional arrow element to render alongside the dropdown menu. This can be used to help visually link the trigger with the `DropdownMenuContent`. Must be rendered inside `DropdownMenuContent`.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"svg"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `height` | `5` | `number` | The height of the arrow in pixels. |
| `rounded` | `false` | `boolean` | When `true`, render the rounded version of arrow. Do not work with `as`/`asChild` |
| `width` | `10` | `number` | The width of the arrow in pixels. |

[DropdownMenuArrow.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuArrow.vue)

### Item

The component that contains the dropdown menu items.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `disabled` |  | `boolean` | When `true`, prevents the user from interacting with the item. |
| `textValue` |  | `string` | Optional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item.<br><br>Use this when the content is complex, or you have non-textual content inside. |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `select` | `event: Event` | Event handler called when the user selects an item (via mouse or keyboard).<br><br>Calling `event.preventDefault` in this handler will prevent the menu from closing when selecting that item. |

[DropdownMenuItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuItem.vue)

| Data attribute | Value |
| --- | --- |
| `[data-orientation]` | "vertical" \\| "horizontal" |
| `[data-highlighted]` | Present when highlighted |
| `[data-disabled]` | Present when disabled |

### Group

Used to group multiple `DropdownMenuItem`s.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |

[DropdownMenuGroup.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuGroup.vue)

### Label

Used to render a label. It won't be focusable using arrow keys.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |

[DropdownMenuLabel.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuLabel.vue)

### CheckboxItem

An item that can be controlled and rendered like a checkbox.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `disabled` |  | `boolean` | When `true`, prevents the user from interacting with the item. |
| `modelValue` |  | `false \| true \| "indeterminate"` | The controlled checked state of the item. Can be used as `v-model`. |
| `textValue` |  | `string` | Optional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item.<br><br>Use this when the content is complex, or you have non-textual content inside. |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `select` | `event: Event` | Event handler called when the user selects an item (via mouse or keyboard).<br><br>Calling `event.preventDefault` in this handler will prevent the menu from closing when selecting that item. |
| `update:modelValue` | `payload: boolean` | Event handler called when the checked state changes. |

**Slots**

| Slot | Payload | Description |
| --- | --- | --- |
| `checked` | `false \| true \| "indeterminate"` | Current checked state |
| `modelValue` | `CheckedState` | Current modelValue state |

[DropdownMenuCheckboxItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuCheckboxItem.vue)

| Data attribute | Value |
| --- | --- |
| `[data-state]` | "checked" \\| "unchecked" \\| "indeterminate" |
| `[data-highlighted]` | Present when highlighted |
| `[data-disabled]` | Present when disabled |

### RadioGroup

Used to group multiple `DropdownMenuRadioItem`s.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `modelValue` |  | `AcceptableValue` | The value of the selected item in the group. |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `update:modelValue` | `payload: AcceptableValue` | Event handler called when the value changes. |

[DropdownMenuRadioGroup.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuRadioGroup.vue)

### RadioItem

An item that can be controlled and rendered like a radio.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `disabled` |  | `boolean` | When `true`, prevents the user from interacting with the item. |
| `textValue` |  | `string` | Optional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item.<br><br>Use this when the content is complex, or you have non-textual content inside. |
| `value*` |  | `AcceptableValue` | The unique value of the item. |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `select` | `event: Event` | Event handler called when the user selects an item (via mouse or keyboard).<br><br>Calling `event.preventDefault` in this handler will prevent the menu from closing when selecting that item. |

**Slots**

| Slot | Payload | Description |
| --- | --- | --- |
| `checked` | `boolean` | Current checked state |

[DropdownMenuRadioItem.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuRadioItem.vue)

| Data attribute | Value |
| --- | --- |
| `[data-state]` | "checked" \\| "unchecked" \\| "indeterminate" |
| `[data-highlighted]` | Present when highlighted |
| `[data-disabled]` | Present when disabled |

### ItemIndicator

Renders when the parent `DropdownMenuCheckboxItem` or `DropdownMenuRadioItem` is checked. You can style this element directly, or you can use it as a wrapper to put an icon into, or both.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `forceMount` |  | `boolean` | Used to force mounting when more control is needed. Useful when<br>controlling animation with Vue animation libraries. |

[DropdownMenuItemIndicator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuItemIndicator.vue)

| Data attribute | Value |
| --- | --- |
| `[data-state]` | "checked" \\| "unchecked" \\| "indeterminate" |

### Separator

Used to visually separate items in the dropdown menu.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |

[DropdownMenuSeparator.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuSeparator.vue)

### Sub

Contains all the parts of a submenu.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `defaultOpen` |  | `boolean` | The open state of the dropdown menu when it is initially rendered. Use when you do not need to control its open state. |
| `open` |  | `boolean` | The controlled open state of the menu. Can be used as `v-model:open`. |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `update:open` | `payload: boolean` | Event handler called when the open state of the submenu changes. |

**Slots**

| Slot | Payload | Description |
| --- | --- | --- |
| `open` | `boolean` | Current open state |

[DropdownMenuSub.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuSub.vue)

### SubTrigger

An item that opens a submenu. Must be rendered inside `DropdownMenuSub`.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `disabled` |  | `boolean` | When `true`, prevents the user from interacting with the item. |
| `graceDuration` | `300` | `number` | Time in milliseconds to keep a submenu open while the pointer moves from<br>its trigger to the submenu. |
| `textValue` |  | `string` | Optional text used for typeahead purposes. By default the typeahead behavior will use the `.textContent` of the item.<br><br>Use this when the content is complex, or you have non-textual content inside. |

[DropdownMenuSubTrigger.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuSubTrigger.vue)

| Data attribute | Value |
| --- | --- |
| `[data-state]` | "open" \\| "closed" |
| `[data-highlighted]` | Present when highlighted |
| `[data-disabled]` | Present when disabled |

| CSS variable | Description |
| --- | --- |
| `--akar-dropdown-menu-content-transform-origin` | The `transform-origin` computed from the content and arrow positions/offsets |
| `--akar-dropdown-menu-content-available-width` | The remaining width between the trigger and the boundary edge |
| `--akar-dropdown-menu-content-available-height` | The remaining height between the trigger and the boundary edge |
| `--akar-dropdown-menu-trigger-width` | The width of the trigger |
| `--akar-dropdown-menu-trigger-height` | The height of the trigger |

### SubContent

The component that pops out when a submenu is open. Must be rendered inside `DropdownMenuSub`.

**Props**

| Prop | Default | Type | Description |
| --- | --- | --- | --- |
| `alignFlip` | `true` | `boolean` | Flip alignment when colliding with boundary.<br>May only occur when `prioritizePosition` is true. |
| `alignOffset` | `0` | `number` | An offset in pixels from the `start` or `end` alignment options. |
| `arrowPadding` | `0` | `number` | The padding between the arrow and the edges of the content.<br>If your content has border-radius, this will prevent it from<br>overflowing the corners. |
| `as` | `"div"` | `AsTag \| Component` | The element or component this component should render as. Can be overwritten by `asChild`. |
| `asChild` |  | `boolean` | Change the default rendered element for the one passed as a child, merging their props and behavior.<br><br>Read our [Composition](https://vinicunca.dev/akar/guides/composition) guide for more details. |
| `avoidCollisions` | `true` | `boolean` | When `true`, overrides the side and align preferences<br>to prevent collisions with boundary edges. |
| `collisionBoundary` | `[]` | `Element \| (Element \| null)[] \| null` | The element used as the collision boundary. By default<br>this is the viewport, though you can provide additional<br>element(s) to be included in this check. |
| `collisionPadding` | `0` | `number \| Partial<Record<"top" \| "right" \| "bottom" \| "left", number>>` | The distance in pixels from the boundary edges where collision<br>detection should occur. Accepts a number (same for all sides),<br>or a partial padding object, for example: { top: 20, left: 20 }. |
| `disableUpdateOnLayoutShift` | `false` | `boolean` | Whether to disable the update position for the content when the layout shifted. |
| `forceMount` |  | `boolean` | Used to force mounting when more control is needed. Useful when<br>controlling animation with Vue animation libraries. |
| `hideShiftedArrow` | `true` | `boolean` | When `true`, hides the arrow when it cannot be centered<br>to the reference element. |
| `hideWhenDetached` | `false` | `boolean` | Whether to hide the content when the trigger becomes fully occluded. |
| `loop` | `false` | `boolean` | When `true`, keyboard navigation will loop from last item to first, and vice versa. |
| `memoDependencies` |  | `unknown[]` | Reactive dependencies that should invalidate the memoized content subtree. |
| `positionStrategy` |  | `"fixed" \| "absolute"` | The type of CSS position property to use. |
| `prioritizePosition` | `false` | `boolean` | Force content to be position within the viewport.<br><br>Might overlap the reference element, which may not be desired. |
| `reference` |  | `ReferenceElement` | The custom element or virtual element that will be set as the reference<br>to position the floating element.<br><br>If provided, it will replace the default anchor element. |
| `sideFlip` | `true` | `boolean` | Flip to the opposite side when colliding with boundary. |
| `sideOffset` | `0` | `number` | The distance in pixels from the trigger. |
| `sticky` | `"partial"` | `"partial" \| "always"` | The sticky behavior on the align axis. `partial` will keep the<br>content in the boundary as long as the trigger is at least partially<br>in the boundary whilst "always" will keep the content in the boundary<br>regardless. |
| `updatePositionStrategy` | `'optimized'` | `"always" \| "optimized"` | Strategy to update the position of the floating element on every animation frame. |

**Events**

| Event | Payload | Description |
| --- | --- | --- |
| `closeAutoFocus` | `event: Event` | Event handler called when auto-focusing on close.<br>Can be prevented. |
| `entryFocus` | `event: Event` |  |
| `escapeKeyDown` | `event: KeyboardEvent` | Event handler called when the escape key is down.<br>Can be prevented. |
| `focusOutside` | `event: FocusOutsideEvent` | Event handler called when the focus moves outside of the `DismissableLayer`.<br>Can be prevented. |
| `interactOutside` | `event: PointerDownOutsideEvent \| FocusOutsideEvent` | Event handler called when an interaction happens outside the `DismissableLayer`.<br>Specifically, when a `pointerdown` event happens outside or focus moves outside of it.<br>Can be prevented. |
| `openAutoFocus` | `event: Event` |  |
| `pointerDownOutside` | `event: PointerDownOutsideEvent` | Event handler called when a `pointerdown` event happens outside of the `DismissableLayer`.<br>Can be prevented. |

[DropdownMenuSubContent.vue source](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu/DropdownMenuSubContent.vue)

| Data attribute | Value |
| --- | --- |
| `[data-state]` | "open" \\| "closed" |
| `[data-side]` | "left" \\| "right" \\| "bottom" \\| "top" |
| `[data-align]` | "start" \\| "end" \\| "center" |
| `[data-orientation]` | "vertical" \\| "horizontal" |

## Examples

### With submenus

You can create submenus by using `DropdownMenuSub` in combination with its parts.

```vue
<script setup lang="ts">
import {
  DropdownMenuArrow,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuPortal,
  DropdownMenuRoot,
  DropdownMenuSeparator,
  DropdownMenuSub,
  DropdownMenuSubContent,
  DropdownMenuSubTrigger,
  DropdownMenuTrigger,
} from 'akar'
</script>

<template>
  <DropdownMenuRoot>
    <DropdownMenuTrigger>…</DropdownMenuTrigger>
    <DropdownMenuPortal>
      <DropdownMenuContent>
        <DropdownMenuItem>…</DropdownMenuItem>
        <DropdownMenuItem>…</DropdownMenuItem>
        <DropdownMenuSeparator />
        <DropdownMenuSub>
          <DropdownMenuSubTrigger>Sub menu →</DropdownMenuSubTrigger>
          <DropdownMenuPortal>
            <DropdownMenuSubContent>
              <DropdownMenuItem>Sub menu item</DropdownMenuItem>
              <DropdownMenuItem>Sub menu item</DropdownMenuItem>
              <DropdownMenuArrow />
            </DropdownMenuSubContent>
          </DropdownMenuPortal>
        </DropdownMenuSub>
        <DropdownMenuSeparator />
        <DropdownMenuItem>…</DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenuPortal>
  </DropdownMenuRoot>
</template>
```

### With disabled items

You can add special styles to disabled items via the `data-disabled` attribute.

```vue
<script setup lang="ts">
import {
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuPortal,
  DropdownMenuRoot,
  DropdownMenuTrigger,
} from 'akar'
</script>

<template>
  <DropdownMenuRoot>
    <DropdownMenuTrigger>…</DropdownMenuTrigger>
    <DropdownMenuPortal>
      <DropdownMenuContent>
        <DropdownMenuItem
          class="DropdownMenuItem"
          disabled
        >
          …
        </DropdownMenuItem>
        <DropdownMenuItem class="DropdownMenuItem">
          …
        </DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenuPortal>
  </DropdownMenuRoot>
</template>
```

```css
/* styles.css */
.DropdownMenuItem[data-disabled] {
  color: gainsboro;
}
```

### With separators

Use the `Separator` part to add a separator between items.

```vue
<script setup lang="ts">
import {
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuPortal,
  DropdownMenuRoot,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from 'akar'
</script>

<template>
  <DropdownMenuRoot>
    <DropdownMenuTrigger>…</DropdownMenuTrigger>
    <DropdownMenuPortal>
      <DropdownMenuContent>
        <DropdownMenuItem>…</DropdownMenuItem>
        <DropdownMenuSeparator />
        <DropdownMenuItem>…</DropdownMenuItem>
        <DropdownMenuSeparator />
        <DropdownMenuItem>…</DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenuPortal>
  </DropdownMenuRoot>
</template>
```

### With labels

Use the `Label` part to help label a section.

```vue
<script setup lang="ts">
import {
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuPortal,
  DropdownMenuRoot,
  DropdownMenuTrigger,
} from 'akar'
</script>

<template>
  <DropdownMenuRoot>
    <DropdownMenuTrigger>…</DropdownMenuTrigger>
    <DropdownMenuPortal>
      <DropdownMenuContent>
        <DropdownMenuLabel>Label</DropdownMenuLabel>
        <DropdownMenuItem>…</DropdownMenuItem>
        <DropdownMenuItem>…</DropdownMenuItem>
        <DropdownMenuItem>…</DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenuPortal>
  </DropdownMenuRoot>
</template>
```

### With checkbox items

Use the `CheckboxItem` part to add an item that can be checked.

```vue
<script setup lang="ts">
import { Icon } from '@iconify/vue'
import {
  DropdownMenuCheckboxItem,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuItemIndicator,
  DropdownMenuPortal,
  DropdownMenuRoot,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from 'akar'
import { ref } from 'vue'

const checked = ref(false)
</script>

<template>
  <DropdownMenuRoot>
    <DropdownMenuTrigger>…</DropdownMenuTrigger>
    <DropdownMenuPortal>
      <DropdownMenuContent>
        <DropdownMenuItem>…</DropdownMenuItem>
        <DropdownMenuItem>…</DropdownMenuItem>
        <DropdownMenuSeparator />
        <DropdownMenuCheckboxItem v-model="checked">
          <DropdownMenuItemIndicator>
            <Icon icon="radix-icons:check" />
          </DropdownMenuItemIndicator>
          Checkbox item
        </DropdownMenuCheckboxItem>
      </DropdownMenuContent>
    </DropdownMenuPortal>
  </DropdownMenuRoot>
</template>
```

### With radio items

Use the `RadioGroup` and `RadioItem` parts to add an item that can be checked amongst others.

```vue
<script setup lang="ts">
import { Icon } from '@iconify/vue'
import {
  DropdownMenuContent,
  DropdownMenuItemIndicator,
  DropdownMenuPortal,
  DropdownMenuRadioGroup,
  DropdownMenuRadioItem,
  DropdownMenuRoot,
  DropdownMenuTrigger,
} from 'akar'
import { ref } from 'vue'

const color = ref(false)
</script>

<template>
  <DropdownMenuRoot>
    <DropdownMenuTrigger>…</DropdownMenuTrigger>
    <DropdownMenuPortal>
      <DropdownMenuContent>
        <DropdownMenuRadioGroup v-model="color">
          <DropdownMenuRadioItem value="red">
            <DropdownMenuItemIndicator>
              <Icon icon="radix-icons:check" />
            </DropdownMenuItemIndicator>
            Red
          </DropdownMenuRadioItem>
          <DropdownMenuRadioItem value="blue">
            <DropdownMenuItemIndicator>
              <Icon icon="radix-icons:check" />
            </DropdownMenuItemIndicator>
            Blue
          </DropdownMenuRadioItem>
          <DropdownMenuRadioItem value="green">
            <DropdownMenuItemIndicator>
              <Icon icon="radix-icons:check" />
            </DropdownMenuItemIndicator>
            Green
          </DropdownMenuRadioItem>
        </DropdownMenuRadioGroup>
      </DropdownMenuContent>
    </DropdownMenuPortal>
  </DropdownMenuRoot>
</template>
```

### With complex items

You can add extra decorative elements in the `Item` parts, such as images.

```vue
<script setup lang="ts">
import {
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuPortal,
  DropdownMenuRoot,
  DropdownMenuTrigger,
} from 'akar'
</script>

<template>
  <DropdownMenuRoot>
    <DropdownMenuTrigger>…</DropdownMenuTrigger>
    <DropdownMenuPortal>
      <DropdownMenuContent>
        <DropdownMenuItem>
          <img src="…">
          Adolfo Hess
        </DropdownMenuItem>
        <DropdownMenuItem>
          <img src="…">
          Miyah Myles
        </DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenuPortal>
  </DropdownMenuRoot>
</template>
```

### Constrain the content/sub-content size

You may want to constrain the width of the content (or sub-content) so that it matches the trigger (or sub-trigger) width. You may also want to constrain its height to not exceed the viewport.

We expose several CSS custom properties such as `--akar-dropdown-menu-trigger-width` and `--akar-dropdown-menu-content-available-height` to support this. Use them to constrain the content dimensions.

```vue
<script setup lang="ts">
import { DropdownMenuContent, DropdownMenuPortal, DropdownMenuRoot, DropdownMenuTrigger } from 'akar'
</script>

<template>
  <DropdownMenuRoot>
    <DropdownMenuTrigger>…</DropdownMenuTrigger>
    <DropdownMenuPortal>
      <DropdownMenuContent
        class="DropdownMenuContent"
        :side-offset="5"
      >
        …
      </DropdownMenuContent>
    </DropdownMenuPortal>
  </DropdownMenuRoot>
</template>
```

```css
/* styles.css */
.DropdownMenuContent {
  width: var(--akar-dropdown-menu-trigger-width);
  max-height: var(--akar-dropdown-menu-content-available-height);
}
```

### Origin-aware animations

We expose a CSS custom property `--akar-dropdown-menu-content-transform-origin`. Use it to animate the content from its computed origin based on `side`, `sideOffset`, `align`, `alignOffset` and any collisions.

```vue
<script setup lang="ts">
import { DropdownMenuContent, DropdownMenuPortal, DropdownMenuRoot, DropdownMenuTrigger } from 'akar'
</script>

<template>
  <DropdownMenuRoot>
    <DropdownMenuTrigger>…</DropdownMenuTrigger>
    <DropdownMenuPortal>
      <DropdownMenuContent class="DropdownMenuContent">
        …
      </DropdownMenuContent>
    </DropdownMenuPortal>
  </DropdownMenuRoot>
</template>
```

```css
/* styles.css */
.DropdownMenuContent {
  transform-origin: var(--akar-dropdown-menu-content-transform-origin);
  animation: scaleIn 0.5s ease-out;
}

@keyframes scaleIn {
  from {
    opacity: 0;
    transform: scale(0);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}
```

### Collision-aware animations

We expose `data-side` and `data-align` attributes. Their values will change at runtime to reflect collisions. Use them to create collision and direction-aware animations.

```vue
<script setup lang="ts">
import { DropdownMenuContent, DropdownMenuPortal, DropdownMenuRoot, DropdownMenuTrigger } from 'akar'
</script>

<template>
  <DropdownMenuRoot>
    <DropdownMenuTrigger>…</DropdownMenuTrigger>
    <DropdownMenuPortal>
      <DropdownMenuContent class="DropdownMenuContent">
        …
      </DropdownMenuContent>
    </DropdownMenuPortal>
  </DropdownMenuRoot>
</template>
```

```css
/* styles.css */
.DropdownMenuContent {
  animation-duration: 0.6s;
  animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);
}
.DropdownMenuContent[data-side="top"] {
  animation-name: slideUp;
}
.DropdownMenuContent[data-side="bottom"] {
  animation-name: slideDown;
}

@keyframes slideUp {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes slideDown {
  from {
    opacity: 0;
    transform: translateY(-10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
```

### With filtering

Use `DropdownMenuFilter` with a computed list to control which items are displayed. This example matches labels without regard to case and displays a message when no items match.

```vue
<script setup lang="ts">
import {
  DropdownMenuContent,
  DropdownMenuFilter,
  DropdownMenuItem,
  DropdownMenuPortal,
  DropdownMenuRoot,
  DropdownMenuTrigger,
  useId,
} from 'akar';
import { computed, ref } from 'vue';

const menuId = useId();
const search = ref('');
const items = [
  { id: 'new-tab', label: 'New Tab' },
  { id: 'new-window', label: 'New Window' },
  { id: 'bookmarks', label: 'Show Bookmarks' },
  { id: 'history', label: 'Show History' },
];
const filteredItems = computed(() =>
  items.filter((item) =>
    item.label.toLowerCase().includes(search.value.toLowerCase()),
  ),
);
</script>

<template>
  <DropdownMenuRoot>
    <DropdownMenuTrigger>Browse actions</DropdownMenuTrigger>
    <DropdownMenuPortal>
      <DropdownMenuContent>
        <DropdownMenuFilter
          v-model="search"
          auto-focus
          aria-label="Filter actions"
          placeholder="Filter actions…"
        />
        <DropdownMenuItem
          v-for="item in filteredItems"
          :id="`${menuId}-${item.id}`"
          :key="item.id"
        >
          {{ item.label }}
        </DropdownMenuItem>
        <div v-if="filteredItems.length === 0">
          No actions found.
        </div>
      </DropdownMenuContent>
    </DropdownMenuPortal>
  </DropdownMenuRoot>
</template>
```

## Accessibility

Adheres to the [Menu Button WAI-ARIA design pattern](https://www.w3.org/WAI/ARIA/apg/patterns/menu-button) and uses [roving tabindex](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/#kbd_roving_tabindex) to manage focus movement among menu items.

### Keyboard Interactions

| Key | Description |
| --- | --- |

```text
When focus is on an item, activates the focused item.

  `,
},
{
  keys: ['Enter'],
  description: `

      When focus is on <Code>DropdownMenuTrigger</Code>, opens the dropdown
      menu and focuses the first item.
      <br />
      When focus is on an item, activates the focused item.

  `,
},
{
  keys: ['ArrowDown'],
  description: `

      When focus is on <Code>DropdownMenuTrigger</Code>, opens the dropdown
      menu.
      <br />
      When focus is on an item, moves focus to the next item.

  `,
},
{
  keys: ['ArrowUp'],
  description: `
    When focus is on an item, moves focus to the previous item.
  `,
},
{
  keys: ['ArrowRight', 'ArrowLeft'],
  description: `

      When focus is on <Code>DropdownMenuSubTrigger</Code>, opens or closes
      the submenu depending on reading direction.

  `,
},
{
  keys: ['Esc'],
  description: `

      Closes the dropdown menu and moves focus to{' '}
      <Code>DropdownMenuTrigger</Code>.

  `,
},
```

]"
/>

#### When focus is on the filter

The input keeps focus while keyboard navigation updates the highlighted item through `aria-activedescendant`.

| Key | Description |
| --- | --- |
| <kbd>ArrowDown</kbd> / <kbd>ArrowUp</kbd> | Highlights the next or previous enabled item. |
| <kbd>Home</kbd> / <kbd>End</kbd> | Highlights the first or last enabled item. |
| <kbd>Enter</kbd> | Activates the highlighted item. |
| <kbd>Esc</kbd> | Clears a non-empty filter without closing the menu. If the filter is empty, closes the menu and returns focus to the trigger. |

## Custom APIs

Create your own API by abstracting the primitive parts into your own component.

### Abstract the arrow and item indicators

This example abstracts the `DropdownMenuArrow` and `DropdownMenuItemIndicator` parts. It also wraps implementation details for `CheckboxItem` and `RadioItem`.

#### Usage

```vue
<script setup lang="ts">
import {
  DropdownMenu,
  DropdownMenuCheckboxItem,
  DropdownMenuContent,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuRadioGroup,
  DropdownMenuRadioItem,
  DropdownMenuSeparator,
  DropdownMenuTrigger,
} from './your-dropdown-menu';
</script>

<template>
  <DropdownMenu>
    <DropdownMenuTrigger>DropdownMenu trigger</DropdownMenuTrigger>
    <DropdownMenuContent>
      <DropdownMenuItem>Item</DropdownMenuItem>
      <DropdownMenuLabel>Label</DropdownMenuLabel>
      <DropdownMenuGroup>Group</DropdownMenuGroup>
      <DropdownMenuCheckboxItem>CheckboxItem</DropdownMenuCheckboxItem>
      <DropdownMenuSeparator>Separator</DropdownMenuSeparator>
      <DropdownMenuRadioGroup>
        <DropdownMenuRadioItem>RadioItem</DropdownMenuRadioItem>
        <DropdownMenuRadioItem>RadioItem</DropdownMenuRadioItem>
      </DropdownMenuRadioGroup>
    </DropdownMenuContent>
  </DropdownMenu>
</template>
```

#### Implementation

```ts
export {
  DropdownMenuRoot as DropdownMenu,
  DropdownMenuGroup,
  DropdownMenuItem,
  DropdownMenuLabel,
  DropdownMenuRadioGroup,
  DropdownMenuSeparator,
  DropdownMenuTrigger
} from 'akar';
export { default as DropdownMenuCheckboxItem } from 'DropdownMenuCheckboxItem.vue';
// your-dropdown-menu.ts
export { default as DropdownMenuContent } from 'DropdownMenuContent.vue';

export { default as DropdownMenuRadioItem } from 'DropdownMenuRadioItem.vue';
```

```vue
<!-- DropdownMenuContent.vue -->
<script setup lang="ts">
import type { DropdownMenuContentEmits, DropdownMenuContentProps } from 'akar';
import { DropdownMenuContent, DropdownMenuPortal, useForwardPropsEmits } from 'akar';

const props = defineProps<DropdownMenuContentProps>();
const emits = defineEmits<DropdownMenuContentEmits>();

const forwarded = useForwardPropsEmits(props, emits);
</script>

<template>
  <DropdownMenuPortal>
    <DropdownMenuContent v-bind="forwarded">
      <slot />
    </DropdownMenuContent>
  </DropdownMenuPortal>
</template>
```

```vue
<!-- DropdownMenuCheckboxItem.vue -->
<script setup lang="ts">
import type { DropdownMenuCheckboxItemEmits, DropdownMenuCheckboxItemProps } from 'akar';
import { CheckIcon } from '@radix-icons/vue';
import { DropdownMenuCheckboxItem, DropdownMenuItemIndicator, useForwardPropsEmits } from 'akar';

const props = defineProps<DropdownMenuCheckboxItemProps>();
const emits = defineEmits<DropdownMenuCheckboxItemEmits>();

const forwarded = useForwardPropsEmits(props, emits);
</script>

<template>
  <DropdownMenuCheckboxItem v-bind="forwarded">
    <DropdownMenuItemIndicator>
      <CheckIcon />
    </DropdownMenuItemIndicator>

    <slot />
  </DropdownMenuCheckboxItem>
</template>
```

```vue
<!-- DropdownMenuRadioItem.vue -->
<script setup lang="ts">
import type { DropdownMenuRadioItemEmits, DropdownMenuRadioItemProps } from 'akar';
import { DotFilledIcon } from '@radix-icons/vue';
import { DropdownMenuItemIndicator, DropdownMenuRadioItem, useForwardPropsEmits } from 'akar';

const props = defineProps<DropdownMenuRadioItemProps>();
const emits = defineEmits<DropdownMenuRadioItemEmits>();

const forwarded = useForwardPropsEmits(props, emits);
</script>

<template>
  <DropdownMenuRadioItem v-bind="forwarded">
    <DropdownMenuItemIndicator>
      <DotFilledIcon />
    </DropdownMenuItemIndicator>

    <slot />
  </DropdownMenuRadioItem>
</template>
```

---

- [ARIA](https://www.w3.org/WAI/ARIA/apg/patterns/menu-button)
- [GitHub](https://github.com/vinicunca/akar/blob/v2.0.20/packages/core/src/DropdownMenu)
- [npm](https://www.npmjs.com/package/akar)


## Sitemap

See the full [sitemap](https://vinicunca.dev/sitemap.md) for all pages.
