Menu
VdMenu is a declarative dropdown menu: pass a label and an items array and it renders an accessible role="menu" popup, reusing the framework's dropdown runtime for toggle, keyboard and outside-click behaviour. To wire hand-written dropdown markup instead, call useDropdown(root).
Actions Menu
Last action: —
<div class="vd-dropdown">
<button type="button" class="vd-btn vd-btn-secondary vd-dropdown-toggle"
data-vd-dropdown-toggle aria-haspopup="menu">Actions</button>
<div class="vd-dropdown-menu" role="menu">
<a class="vd-dropdown-item" role="menuitem" href="#">Edit</a>
<a class="vd-dropdown-item" role="menuitem" href="#">Duplicate</a>
<div class="vd-dropdown-divider" role="separator"></div>
<a class="vd-dropdown-item is-disabled" role="menuitem" aria-disabled="true">Archived</a>
<a class="vd-dropdown-item" role="menuitem" href="#">Delete</a>
</div>
</div>
<!-- Wire hand-written dropdown markup with useDropdown(root), or just render <VdMenu> (below). -->End-Aligned
Sorting by: —
<div class="vd-dropdown">
<button type="button" class="vd-btn vd-btn-secondary vd-dropdown-toggle"
data-vd-dropdown-toggle aria-haspopup="menu">Sort</button>
<div class="vd-dropdown-menu vd-dropdown-menu-end" role="menu">
<a class="vd-dropdown-item" role="menuitem" href="#">Newest first</a>
<a class="vd-dropdown-item" role="menuitem" href="#">Oldest first</a>
<a class="vd-dropdown-item" role="menuitem" href="#">A → Z</a>
</div>
</div>Link Menu
Items with an href navigate instead of emitting.
<script setup lang="ts">
import { VdMenu } from "@vanduo-oss/vd3";
const items = [
{ label: "Edit", value: "edit" },
{ label: "Duplicate", value: "duplicate" },
{ divider: true },
{ label: "Delete", value: "delete" },
];
const onSelect = (value: string) => console.log(value);
</script>
<template>
<VdMenu label="Actions" :items="items" @select="onSelect" />
</template>API Reference
Usage
<script setup lang="ts">
import { VdMenu } from "@vanduo-oss/vd3";
const items = [
{ label: "Edit", value: "edit" },
{ label: "Duplicate", value: "duplicate" },
{ divider: true },
{ label: "Delete", value: "delete" },
];
const onSelect = (value: string) => console.log(value);
</script>
<template>
<VdMenu label="Actions" :items="items" @select="onSelect" />
</template>CSS Classes
| Class | Description |
|---|---|
.vd-dropdown | Positioning wrapper around the trigger and the menu |
.vd-dropdown-toggle | The trigger button. `data-vd-dropdown-toggle` wires the dropdown runtime |
.vd-dropdown-menu | The popup list; absolutely positioned under the toggle |
.vd-dropdown-menu-end | Aligns the menu to the trigger's end edge |
.vd-dropdown-item | An individual menu entry (rendered as <a>) |
.vd-dropdown-item.is-disabled | Non-interactive item; pair with aria-disabled |
.vd-dropdown-divider | A separator rule between groups of items |
Component API
| Prop / event | Description |
|---|---|
:label | Text shown on the trigger button. |
:items | Array of { label, value?, href?, disabled?, divider? }. value defaults to label. |
:align | 'start' | 'end' — which edge the menu aligns to (default 'start'). |
@select | Fired with the chosen item's value (or label). Dividers / disabled items don't emit. |
Events
| Event | Description |
|---|---|
select | (Vue) Emitted with the chosen item's value (or its label when no value is set). Items that are dividers, disabled, or links don't emit. |
Accessibility
- The trigger declares
aria-haspopup="menu"and the popup carriesrole="menu"with each entry asrole="menuitem". - Disabled items set
aria-disabled="true"and don't fireselect; dividers userole="separator". - The shared dropdown runtime handles Esc to close, outside-click dismissal, and keyboard focus management.