Button Menu
UiButtonMenu renders a button that opens a dropdown. Fill its #menu slot with UiButtonMenuItem, UiButtonMenuSubmenu, UiButtonMenuDivider, and UiButtonMenuText; items take their label from item-text.
Build a menu
<template>
<UiButtonMenu variant="outline" text="Actions">
<template #menu>
<UiButtonMenuText item-text="Manage" />
<UiButtonMenuItem item-text="Edit" icon="" />
<UiButtonMenuItem item-text="Duplicate" icon="" shortcut="Ctrl+D" />
<UiButtonMenuDivider />
<UiButtonMenuItem item-text="Delete" icon="" is-destructive />
</template>
</UiButtonMenu>
</template>
Add a submenu
<template>
<UiButtonMenu text="More">
<template #menu>
<UiButtonMenuItem item-text="Share" icon="" />
<UiButtonMenuSubmenu item-text="Export" icon="" placement="right">
<UiButtonMenuItem item-text="PDF" />
<UiButtonMenuItem item-text="CSV" />
</UiButtonMenuSubmenu>
</template>
</UiButtonMenu>
</template>
Keyboard
The menu follows the WAI-ARIA menu button pattern. Enter, Space, ↓ or ↑ on the button open the menu and focus its first item (↑ focuses the last).
| Key | In the menu |
|---|---|
| ↓ / ↑ | Next / previous item, wrapping at the ends |
| Home / End | First / last item |
| A letter | Next item whose label starts with it |
| → / ← | Open a submenu on its first item / close it back to its item |
| Enter / Space | Pick the item |
| Esc | Close the menu (not a dialog around it) and focus the button |
| Tab | Close the menu and move to the next element |
After an item is picked from the keyboard, focus goes back to the button; after a click it stays where the click left it. Disabled items are skipped. The panel is a role="menu", items are menuitems (or menuitemcheckboxes with checked) and dividers are separators.
UiButtonMenu props
Takes UiButton's look and state props (id, text, title, variant, color, size, icon, iconVariant, iconTrailing, disabled, loading, rounded, fluid, customClass). The trigger is always a button, so the link props (to, href, as) and type don't apply. It adds:
| Prop | Type | Default | Description |
|---|---|---|---|
placement | FloatingPlacement | 'bottom' | Dropdown placement (top, bottom, left, right, …). |
tooltipText | string | null | null | Tooltip on the trigger, and its accessible name when there is no text or title. Without it, an icon-only trigger is named by the buttonMenu.ariaLabel label ("Menu"). |
tooltipPlacement | FloatingPlacement | 'top' | Tooltip placement. |
isMobile | boolean | false | Disable dropdown positioning (bottom sheet on mobile). |
Slots: menu (the dropdown content), icon (the trigger icon).
Emits: click (with the MouseEvent).
UiButtonMenuItem props
| Prop | Type | Default | Description |
|---|---|---|---|
itemText | string | — | Item label. |
icon | string | null | — | Leading Material Symbols code. |
iconClass / iconStyle | string | string[] | null / string | object | null | — | Classes and inline styles for the leading icon. |
iconTrailing | string | null | — | Trailing icon code. |
iconTrailingClass / iconTrailingStyle | string | string[] | null / string | object | null | — | Classes and inline styles for the trailing icon. |
badge | Partial<IBadgeProps> | null | — | Inline badge config. |
shortcut | string | null | — | Shortcut hint (e.g. Ctrl+S). |
isDestructive | boolean | false | Destructive (danger) styling. |
disabled | boolean | false | Disable the item. |
keepOpen | boolean | false | Keep the menu open after a click. By default a click closes the menu and any parent submenu. |
checked | boolean | null | null | Make the item a checkbox (role="menuitemcheckbox") in this state. Pair it with keepOpen for toggles. |
customClass | string | string[] | null | — | Extra classes on the item. |
UiButtonMenuSubmenu props
The submenu takes an item's look (itemText, icon, iconClass, iconStyle, iconTrailing, iconTrailingClass, iconTrailingStyle, badge, isDestructive, disabled, customClass) and fills its default slot with the nested items. → opens it on its first item and ← closes it.
| Prop | Type | Default | Description |
|---|---|---|---|
id | string | null | — | Id of the nested dropdown. |
placement | FloatingPlacement | 'right' | Where the submenu opens. |
isMobile | boolean | false | Disable positioning (bottom sheet on mobile). |
CSS variables
The menu panel (.v-popper--theme-dropdown, shared by every dropdown) reads these variables. Set them on :root to restyle all menus. The mobile bottom sheet keeps its larger item padding and corners. Hover and pressed backgrounds come from the shared state layer.
:root {
--cffy-dropdown-radius: var(--cffy-radius-md);
--cffy-dropdown-item-active-bg-color: var(--cffy-primary-container);
--cffy-dropdown-item-active-color: var(--cffy-on-primary-container);
}
| Variable | Default | Controls |
|---|---|---|
--cffy-dropdown-bg-color / --cffy-dropdown-color | --cffy-surface-overlay / --cffy-on-background | Panel background and text |
--cffy-dropdown-border-color | --cffy-outline-overlay | Panel border |
--cffy-dropdown-radius | --cffy-shape-container | Panel corners (items use half) |
--cffy-dropdown-shadow | --cffy-shadow-lg | Panel shadow |
--cffy-dropdown-padding | --cffy-space-4 | Panel padding |
--cffy-dropdown-min-width | 12rem | Panel minimum width |
--cffy-dropdown-easing / --cffy-dropdown-duration | --cffy-ease-overshoot-soft / --cffy-duration-500 | Opening animation |
--cffy-dropdown-item-color | the panel text color | Item text |
--cffy-dropdown-item-font-size | --cffy-fs-3xs | Item text size |
--cffy-dropdown-item-radius | half the panel radius | Item corners |
--cffy-dropdown-item-padding-inline / --cffy-dropdown-item-padding-block | --cffy-space-8 / --cffy-space-8 | Item padding |
--cffy-dropdown-item-hover-color | --cffy-on-background | Hovered item text |
--cffy-dropdown-item-active-color / --cffy-dropdown-item-active-bg-color | --cffy-on-background / --cffy-surface-container-highest | Selected, focused and pressed item |
Related components
UiButtonMenuDivider— visual separator.UiButtonMenuText— non-interactive label (itemText).