---
title: "DropdownMenu"
description: "A menu of short commands that opens from a trigger."
category: Navigation
status: beta
since: 0.3.4
tags: [dropdown, menu, popover]
syncStatus: reviewed
verified: true
---

## Usage

### Basic
A selection blinks to confirm, then closes the menu; an item with `activation-feedback="false"` runs at once.
:::TuffDemoWrapper{demo="DropdownMenuDropdownMenuDemo" code-lang="vue"}
---
code: |
  <template>
    <TxDropdownMenu>
      <template #trigger>
        <TxButton>Menu</TxButton>
      </template>

      <TxDropdownItem>Open (confirm blink)</TxDropdownItem>
      <TxDropdownItem :activation-feedback="false">Run immediately (feedback off)</TxDropdownItem>
      <TxDropdownItem danger>Delete</TxDropdownItem>
    </TxDropdownMenu>
  </template>
---
:::

### Submenus
`TxDropdownSubmenu` nests child panels to any depth; hovering the trigger row expands one.
:::TuffDemoWrapper{demo="DropdownMenuDropdownSubmenuDemo" code-lang="vue"}
---
code: |
  <template>
    <TxDropdownMenu>
      <template #trigger>
        <TxButton>Actions</TxButton>
      </template>

      <TxDropdownItem>Open</TxDropdownItem>
      <TxDropdownSubmenu>
        Export as…
        <template #menu>
          <TxDropdownItem>PNG</TxDropdownItem>
          <TxDropdownItem>SVG</TxDropdownItem>
          <TxDropdownSubmenu>
            More formats
            <template #menu>
              <TxDropdownItem>WebP</TxDropdownItem>
              <TxDropdownItem>AVIF</TxDropdownItem>
            </template>
          </TxDropdownSubmenu>
        </template>
      </TxDropdownSubmenu>
    </TxDropdownMenu>
  </template>
---
:::

### Navigation Style
The `trigger` slot takes any element; the `right` slot replaces an item's trailing arrow.
:::TuffDemoWrapper{demo="DropdownMenuDropdownMenuNavDemo" code-lang="vue"}
---
code: |
  <template>
    <TxDropdownMenu v-model="open" :min-width="240">
      <template #trigger>
        <div class="nav-trigger">
          Design <span>Ecosystem</span>
          <TxIcon name="chevron-down" />
        </div>
      </template>

      <TxDropdownItem>
        GitHub
        <template #right>
          <i class="i-carbon-launch" />
        </template>
      </TxDropdownItem>
      <TxDropdownItem>
        NPM
        <template #right>
          <i class="i-carbon-launch" />
        </template>
      </TxDropdownItem>
    </TxDropdownMenu>
  </template>
---
:::

### Dashboard Navigation
`TxTabs` hold the top-level sections; light actions go in `TxDropdownMenu`, short notes in `TxPopover`, and dense settings in `TxDrawer`.
:::TuffDemoWrapper{demo="ComponentsNavigationShellDemo" code-lang="vue"}
---
code: |
  <template>
    <TxDropdownMenu>
      <template #trigger>
        <TxButton>Release actions</TxButton>
      </template>
      <TxDropdownItem>Quick release</TxDropdownItem>
    </TxDropdownMenu>

    <TxPopover>
      <template #reference>
        <TxButton variant="secondary">Policy notes</TxButton>
      </template>
      Keep popovers short and action-light.
    </TxPopover>

    <TxTabs v-model="active" placement="left" indicator-variant="pill">
      <TxTabItem name="Overview" activation>Overview settings</TxTabItem>
      <TxTabItem name="Releases">Release settings</TxTabItem>
    </TxTabs>

    <TxDrawer v-model:visible="drawerVisible" title="Release policy" />
  </template>
---
:::

### Best Practices

- Keep it to short commands. For paragraphs, forms, or multi-step interaction, use `TxPopover`, `TxDrawer`, or `TxContextMenuPanel`.
- Use `danger` only for destructive commands, and group them apart from neutral ones as the list grows.
- Use `arrow` only on navigation or submenu rows; put external-link icons, shortcuts, and status badges in the `right` slot.
- Set `closeOnSelect=false` only on rows that open another surface or start a multi-step flow. Turn off `activationFeedback` only when the host gives stronger feedback or needs a synchronous callback.
- Set `initialFocus="none"` only when the host places focus itself after opening, such as on a search field in the panel; otherwise keyboard users need an extra arrow press to reach the list.

## API Reference

### TxDropdownMenu

#### Props

| Prop | Type | Default | Description |
|------|------|---------|------|
| `modelValue` | `boolean` | `undefined` | Open state (`v-model`); omit it to leave the menu uncontrolled. |
| `trigger` | `'click' \| 'hover'` | `'click'` | Trigger mode; `TxPopover` handles hover timing and mutual exclusion. |
| `placement` | `DropdownPlacement` | `'bottom-start'` | Panel position relative to the trigger. |
| `offset` | `number` | `6` | Distance between the trigger and the panel, in px. |
| `closeOnSelect` | `boolean` | `true` | Closes the menu after an enabled item emits `select`. |
| `activationFeedback` | `boolean` | `true` | Clears, then confirms the highlight for 90 ms each before closing; skipped under reduced motion. |
| `initialFocus` | `'first-item' \| 'none'` | `'first-item'` | Where focus lands on open; `'none'` leaves it for the host to place. |
| `animation` | `BaseAnchorAnimationOptions` | `{}` | Panel animation; an empty object uses BaseAnchor's default. |
| `minWidth` | `number` | `220` | Minimum panel width in px; the maximum is fixed at 360px. |
| `maxHeight` | `number` | `420` | Maximum panel height in px; taller content scrolls. |
| `unlimitedHeight` | `boolean` | `false` | Removes the panel's height limit. |
| `referenceClass` | `BaseAnchorClassValue` | - | Extra class on the trigger anchor. |
| `panelCard` | `BaseAnchorPanelCardProps` | - | Card props forwarded to the panel. |
| `panelVariant` | `'solid' \| 'dashed' \| 'plain'` | `'solid'` | Panel border style. |
| `panelBackground` | `'pure' \| 'mask' \| 'blur' \| 'glass' \| 'refraction'` | `'refraction'` | Panel background effect. |
| `panelShadow` | `'none' \| 'soft' \| 'medium'` | `'soft'` | Panel shadow. |
| `panelRadius` | `number` | `18` | Panel corner radius in px. |
| `panelPadding` | `number` | `8` | Panel padding in px. |

#### Events

| Event | Params | Description |
|------|------|------|
| `update:modelValue` | `(value: boolean)` | Fires when the menu requests an open-state change. |
| `open` | - | Fires when the menu requests opening. |
| `close` | - | Fires when the menu requests closing. |

#### Slots

| Slot | Props | Description |
|------|-------|-------------|
| `trigger` | - | Trigger content, used as the Popover reference. |
| `default` | - | Menu rows, usually `TxDropdownItem`. |

### TxDropdownItem

#### Props

| Prop | Type | Default | Description |
|------|------|---------|------|
| `disabled` | `boolean` | `false` | Prevents selection; the menu stays open. |
| `danger` | `boolean` | `false` | Danger text styling. |
| `arrow` | `boolean` | `false` | Shows a trailing arrow when there is no `right` slot. |
| `closeOnSelect` | `boolean` | `undefined` | Per-item override of the menu's `closeOnSelect`. |
| `activationFeedback` | `boolean` | `undefined` | Per-item override of the menu's confirmation feedback. |

#### Events

| Event | Params | Description |
|------|------|------|
| `select` | - | Fires on selection, without a payload; a closing item with feedback fires after the 180 ms confirmation. |

#### Slots

| Slot | Props | Description |
|------|-------|-------------|
| `default` | - | Main label. |
| `right` | - | Replaces the trailing arrow drawn by `arrow`. |

### TxDropdownSubmenu

#### Props

| Prop | Type | Default | Description |
|------|------|---------|------|
| `disabled` | `boolean` | `false` | Disables the trigger row; the child panel no longer opens. |
| `placement` | `DropdownPlacement` | `'right-start'` | Child panel position relative to the trigger row. |
| `offset` | `number` | `4` | Distance between the trigger row and the child panel, in px. |
| `width` | `number` | `0` | Fixed child panel width; `0` sizes to content, bounded by `minWidth`. |
| `minWidth` | `number` | `160` | Minimum child panel width in px. |
| `maxHeight` | `number` | `420` | Maximum child panel height in px; taller content scrolls. |
| `unlimitedHeight` | `boolean` | `false` | Removes the child panel's height limit. |
| `animation` | `BaseAnchorAnimationOptions` | `{}` | Child panel animation. |
| `panelCard` | `BaseAnchorPanelCardProps` | - | Card props forwarded to the child panel. |
| `panelVariant` | `'solid' \| 'dashed' \| 'plain'` | `'solid'` | Child panel border style. |
| `panelBackground` | `'pure' \| 'mask' \| 'blur' \| 'glass' \| 'refraction'` | `'refraction'` | Child panel background effect. |
| `panelShadow` | `'none' \| 'soft' \| 'medium'` | `'soft'` | Child panel shadow. |
| `panelRadius` | `number` | `14` | Child panel corner radius in px. |
| `panelPadding` | `number` | `6` | Child panel padding in px. |

#### Slots

| Slot | Props | Description |
|------|-------|-------------|
| `default` | - | Trigger row label. |
| `right` | - | Trailing info on the trigger row, before the arrow. |
| `menu` | - | Child panel content; may nest another `TxDropdownSubmenu`. |

## Overview

- It wraps `TxPopover`, so placement, height limits, panel card props, and animation follow the same anchor behavior.
- A closing selection first clears the highlight, confirms with the `TxCardItem` active state, then emits `select` and closes; other selections emit at once. Disabled items neither select nor close.
- The panel is `role="menu"` and items are `role="menuitem"`. Opening focuses the first enabled item unless `initialFocus="none"`.
- Keyboard: `ArrowDown` / `ArrowUp` move with wraparound and enter the list from a search field; `Home` / `End` jump to the ends, except inside an `input`, `textarea`, or `contenteditable`, where they move the caret.
- Submenus: `ArrowRight` / `Enter` on the trigger row expand and focus the first item, `ArrowLeft` in the child collapses it. Child items close the whole chain per the root's `closeOnSelect`; clicks inside a child aren't outside clicks, and closing a parent closes its children.
- A hover bridge covers the 4px gap between parent and child panels. Sibling submenu rows crossed on a diagonal don't expand; resting on one for about 100 ms switches to it.

## Technologies

- Activation feedback runs on `packages/tuffex/packages/utils/menu-activation-feedback.ts`, shared with ContextMenu.
- Source: `packages/tuffex/packages/components/src/dropdown-menu/`.

<TuffDocSourceLink />
