Row actions
Offer several commands without crowding each row.
Components / Overlays
A keyboard accessible list of actions.
Offer several commands without crowding each row.
Use checkbox items for menu choices that stay selected after the menu closes.
<script setup lang="ts">
import DropdownMenu from './components/ui/dropdown-menu/DropdownMenu.vue'
import DropdownMenuTrigger from './components/ui/dropdown-menu/DropdownMenuTrigger.vue'
import DropdownMenuContent from './components/ui/dropdown-menu/DropdownMenuContent.vue'
import DropdownMenuItem from './components/ui/dropdown-menu/DropdownMenuItem.vue'
import DropdownMenuSeparator from './components/ui/dropdown-menu/DropdownMenuSeparator.vue'
function runAction(action: { id: string }) { console.log(action.id) }
</script>
<template>
<DropdownMenu align="end" :width="240" @select="runAction">
<DropdownMenuTrigger aria-label="Open account menu">•••</DropdownMenuTrigger>
<DropdownMenuContent aria-label="Account actions">
<div class="px-3 py-2">
<p class="font-semibold">Acme Studio</p>
<p class="text-xs text-muted-foreground">Pro workspace</p>
</div>
<DropdownMenuSeparator />
<DropdownMenuItem id="profile" label="View profile" shortcut="⇧⌘P">
<template #prefix><span aria-hidden="true">◉</span></template>
View profile
</DropdownMenuItem>
<DropdownMenuItem id="settings" label="Settings" shortcut="⌘," />
<DropdownMenuItem id="duplicate" label="Duplicate workspace" />
<DropdownMenuSeparator />
<DropdownMenuItem id="archive" label="Archive workspace" destructive />
</DropdownMenuContent>
</DropdownMenu>
</template>A selected item emits its ID to application code.
<script setup lang="ts">
import DropdownMenu from './components/ui/dropdown-menu/DropdownMenu.vue'
import DropdownMenuTrigger from './components/ui/dropdown-menu/DropdownMenuTrigger.vue'
import DropdownMenuContent from './components/ui/dropdown-menu/DropdownMenuContent.vue'
import DropdownMenuItem from './components/ui/dropdown-menu/DropdownMenuItem.vue'
import DropdownMenuSeparator from './components/ui/dropdown-menu/DropdownMenuSeparator.vue'
</script>
<template>
<DropdownMenu @select="$emit('action', $event.id)">
<DropdownMenuTrigger>Project actions</DropdownMenuTrigger>
<DropdownMenuContent aria-label="Project actions">
<DropdownMenuItem id="rename" label="Rename">Rename</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem id="archive" label="Archive" destructive>Archive</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</template>The checked model remains in application state.
<script setup lang="ts">
import { ref } from 'vue'
import DropdownMenu from './components/ui/dropdown-menu/DropdownMenu.vue'
import DropdownMenuTrigger from './components/ui/dropdown-menu/DropdownMenuTrigger.vue'
import DropdownMenuContent from './components/ui/dropdown-menu/DropdownMenuContent.vue'
import DropdownMenuCheckboxItem from './components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue'
const showArchived = ref(false)
</script>
<template>
<DropdownMenu>
<DropdownMenuTrigger>Display options</DropdownMenuTrigger>
<DropdownMenuContent aria-label="Display options">
<DropdownMenuCheckboxItem id="archived" label="Show archived" v-model:checked="showArchived">Show archived</DropdownMenuCheckboxItem>
</DropdownMenuContent>
</DropdownMenu>
</template>The most useful props, models, slots, events, and methods for this component.
| Name | Type | Default or requirement |
|---|---|---|
items | DropdownMenuItemData[] | optional |
DropdownMenuContent aria-label | string | required for unnamed menu |
select | event with selected item | — |
Checkbox / Radio / Submenu parts | compound children | optional |
Item #prefix / #suffix | slots at item edges | optional |
align / side | start | center | end / top | bottom | start / bottom |
Items, checkbox/radio choices, groups, and nested submenus share roving focus, typeahead, RTL-aware arrows, and layer-local Escape handling.