Menu
A dropdown menu positioned relative to a trigger. Supports plain items, checkboxes, radio groups, separators, labels, submenus, and grouped item arrays.
Anatomy
#trigger: Element that opens the menu.#[item.slot]: Per-item render override when an item has aslotkey.
Items are rendered internally from the items prop. Individual items can be overridden via named slots using item.slot.
Usage
Examples
Grouped items with separators
Pass an array of arrays. Akaza UI inserts separators between groups.
<script setup lang="ts">
const items = [
[
{ label: "Edit", value: "edit" },
{ label: "Rename", value: "rename" },
],
[
{ label: "Delete", value: "delete" },
],
];
</script>
<template>
<Menu :items="items">
<template #trigger="{ toggle }">
<button @click="toggle">More ▾</button>
</template>
</Menu>
</template>
Checkbox items
Use checkbox item types for toggles inside a menu.
<script setup lang="ts">
const items = [
{ type: "checkbox", label: "Show sidebar", checked: true, value: "sidebar",
onUpdateChecked: (v) => console.log("sidebar:", v) },
{ type: "checkbox", label: "Compact mode", checked: false, value: "compact",
onUpdateChecked: (v) => console.log("compact:", v) },
];
</script>
Radio group
Use radio items when only one value in a named group can be selected.
<script setup lang="ts">
import { ref } from "vue";
const radioValues = ref({ view: "list" });
const items = [
{ type: "radio", label: "Grid", value: "grid", radioGroup: "view" },
{ type: "radio", label: "List", value: "list", radioGroup: "view" },
];
</script>
<template>
<Menu :items="items" v-model:radio-values="radioValues">
<template #trigger="{ toggle }">
<button @click="toggle">View ▾</button>
</template>
</Menu>
</template>
Submenu
Use children for nested actions that should open as a submenu.
<script setup lang="ts">
const items = [
{ label: "Share", children: [
{ label: "Copy link", value: "copy-link" },
{ label: "Send email", value: "send-email" },
]},
];
</script>
Reactive styling and nested menus
Changes to ui, radio values, and close-on-select settings remain reactive in nested panels. Item values containing quotes or brackets are treated as data, not interpolated into CSS selectors. Stateful label slots retain component identity during ordinary updates.
API Reference
Props
| Prop | Type | Default | Description |
|---|---|---|---|
items | MenuItem[] | MenuItem[][] | — | Flat array or grouped array (groups get auto-separators). |
side | "top" | "bottom" | "left" | "right" | "bottom" | Preferred side to position the menu. |
align | "start" | "center" | "end" | "start" | Alignment relative to the trigger. |
sideOffset | number | 4 | Gap in px between trigger and menu. |
closeOnSelect | boolean | true | Close the menu after an item is selected. |
radioValues | Record<string, string> | — | v-model:radio-values — state for radio groups. |
teleport | string | false | false | Teleport target for the menu. |
as | string | Component | "div" | Root element tag. |
ui | MenuUi | — | CSS class overrides. |
MenuItem
| Key | Type | Description |
|---|---|---|
label | string | Display label. |
value | string | Unique value identifier. |
type | "item" | "checkbox" | "radio" | "separator" | "label" | Item type. Defaults to "item". |
disabled | boolean | Disables this item. |
checked | boolean | Checked state for checkbox items. |
onUpdateChecked | (checked: boolean) => void | Called when a checkbox item changes. |
radioGroup | string | Radio group key for radio items. |
children | MenuItem[] | MenuItem[][] | Sub-menu items. |
slot | string | Named slot key for per-item render override. |
onSelect | () => void | Per-item select callback. |
Slots
| Slot | Scoped props | Description |
|---|---|---|
trigger | { isOpen, open, close, toggle, triggerProps } | The element that opens the menu. |
[item.slot] | { item } | Per-item render override when item.slot is set. |
Exposed methods
| Method | Signature | Description |
|---|---|---|
open | (reason?, event?) => void | Opens the menu. |
close | (reason?, event?) => void | Closes the menu. |
toggle | (reason?, event?) => void | Toggles the menu. |
Emits
| Event | Payload | Description |
|---|---|---|
open-change | [open: boolean, details] | Fired when the open state changes. |
select | [item: MenuItem, details] | Fired when an item is selected. |
check-change | [item: MenuItem, checked: boolean, details] | Fired when a checkbox item changes. |
radio-change | [group: string, value: string, details] | Fired when a radio item is selected. |
update:radioValues | [values: Record<string, string>] | v-model event for radio group state. |
UI Options
| Key | Description |
|---|---|
root | Trigger wrapper/root. |
content | The floating menu panel. |
panel | Inner role="menu" panel. |
item | Shared menu item class for regular, checkbox, radio, and submenu trigger items. |
checkboxItem | Checkbox item element. |
radioItem | Radio item element. |
separator | Separator elements between groups. |
label | Label-type item elements. |
group | Group wrapper element. |
submenu | Submenu wrapper. |
submenuTrigger | Submenu trigger item. |
submenuContent | Submenu panel element. |
Styling Hooks
| UI key | CSS class | Data attrs |
|---|---|---|
root | akaza-menu-root | data-akaza-state |
content | akaza-menu-content | data-akaza-state, data-akaza-side, data-akaza-align |
panel | akaza-menu-panel | — |
group | akaza-menu-group | — |
item | akaza-menu-item | data-akaza-disabled, data-akaza-highlighted |
checkboxItem | akaza-menu-checkbox-item | data-akaza-state, data-akaza-disabled, data-akaza-highlighted |
radioItem | akaza-menu-radio-item | data-akaza-state, data-akaza-disabled, data-akaza-highlighted |
separator | akaza-menu-separator | — |
label | akaza-menu-label | — |
submenu | akaza-menu-submenu | data-akaza-state |
submenuTrigger | akaza-menu-submenu-trigger | data-akaza-state, data-akaza-disabled, data-akaza-highlighted |
submenuContent | akaza-menu-submenu-content | data-akaza-submenu |
Keyboard
| Key | Behavior |
|---|---|
ArrowDown / ArrowUp | Moves focus through enabled items and loops. |
Home / End | Focuses first or last enabled item. |
Enter / Space | Activates item, checkbox, radio, or opens submenu. |
ArrowRight | Opens focused submenu and moves into it; reversed in RTL. |
ArrowLeft | Closes submenu and restores submenu-trigger focus; reversed in RTL. |
Escape | Closes submenu level or whole menu. |
| Printable characters | Typeahead focuses first matching item within 500 ms buffer. |
Opening focuses first enabled item. Trigger keyboard activation comes from trigger element supplied by user; apply triggerProps and use a native button.