Skip to content

Button dropdown โ€‹

A row of actions that stays flat while it's short and collapses behind a โ‹ฎ menu once it isn't. <mono-button-dropdown :buttons.prop="actions" :min="1"> โ€” button plus dropdown in one element.

ts
import 'mono-helper/ui/button-dropdown'

const actions = [
  { label: 'Save', icon: 'i-mdi-content-save', color: 'primary', onClick: save },
  { label: 'Delete', icon: 'i-mdi-delete', color: 'danger', variant: 'outline', onClick: remove },
]
vue
<mono-button-dropdown :buttons.prop="actions" :min="1" />

buttons and trigger are objects, so bind them with .prop โ€” a plain attribute would only carry a stringified value.

How min decides โ€‹

min is how many entries may render inline. It's all-or-nothing: while buttons.length <= min every entry is a plain button; past that they all move into the dropdown and only the trigger is left.

minbuttonsrenders
11that button, directly
13โ‹ฎ โ†’ the three in a menu
33all three inline

Entries are real buttons โ€‹

Each entry is rendered as an actual <mono-button>, so every button prop keeps working โ€” variant, color, size, disabled, badge, icon-position, and the behavioural ones like loading, throttle / debounce and handler. Nothing is re-implemented, so a prop added to the button later works here for free.

On top of ButtonProps, an entry takes label, icon and onClick.

Entries look different inside the menu โ€‹

A dropdown of solid, outlined and tonal buttons in assorted colours reads as noise rather than a list. So inside the menu every row is the same flat, square, borderless strip, and an entryโ€™s own color is expressed by its icon alone โ€” no rounded corners and no press "twitch". The moment the list is short enough to render inline, each entry goes back to its real button styling: gradient fills, outlines, radius, press effect and all.

The โ‹ฎ trigger is styled separately, with color / variant / size on the element itself.

Props โ€‹

PropPurpose
buttonsThe actions. Each entry takes every <mono-button> prop plus label / icon / onClick. Bind with .prop.
minHow many entries may render inline (default 1).
color / variant / sizeStyle the โ‹ฎ trigger. Entries are NOT colored inside the menu โ€” see below.
triggerButtonProps for the โ‹ฎ button โ€” size, variant, a different icon, or a label to make it a normal labelled button.
placementWhere the panel opens (default bottom-end).
offsetGap in px between trigger and panel (default 4).
model-valueOpen state. Listen for mno-open / mno-close to mirror it.
close-on-selectClose when an entry is clicked (default true).
close-on-outside-click / close-on-escapeBoth default true.
disabledDisables the trigger and every entry.

mno-click fires with { item, index, collapsed } in addition to the entry's own onClick, so you can handle actions per-item or centrally.

Keyboard

โ†‘ / โ†“ move between menu rows, Enter activates, Esc closes and returns focus to the trigger.

Both demos also run under Vue + Shadow DOM โ€” same behaviour, icons included.

Types โ€‹

Importimport { ButtonDropdownProps } from 'mono-helper'
PropValueDefaultDescription
buttonsButtonDropdownItem[]โ€”The actions. Each entry takes every `<mono-button>` prop.
minnumberโ€”How many entries may render inline. While `buttons.length <= min` they are all shown as plain buttons; past that, ALL of them move into the dropdown and only the trigger remains. Default `1`.
color'primary' | 'secondary' | 'success' | 'danger' | 'warning' | 'info' | 'teal' | 'purple' | 'dark' | 'light'โ€”Colors the `โ‹ฎ` trigger. Entries are deliberately NOT colored inside the menu โ€” an entry's own `color` tints its ICON there instead, since a list of differently-coloured buttons reads as noise. Outside the menu (inline, when the list is short enough) entries keep their real button styling.
variant'solid' | 'outline' | 'tonal' | 'gradient'โ€”Visual style of the `โ‹ฎ` trigger โ€” same values `<mono-button>` takes.
size'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl'โ€”Size of the `โ‹ฎ` trigger.
placement'left' | 'right' | 'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end' | 'left-start' | 'left-end' | 'right-start' | 'right-end'โ€”Where the panel opens relative to the trigger. Default `'bottom-end'`.
offsetnumberโ€”Gap in px between trigger and panel. Default `4`.
triggerButtonProps & { label?: string | undefined; icon?: string | undefined; }โ€”Props for the `โ‹ฎ` trigger button โ€” same shape as an entry, minus the click.
modelValuebooleanโ€”Open state. Two-way is opt-in: listen for `mno-open` / `mno-close`.
disabledbooleanโ€”Disables the trigger and every entry.
closeOnSelectbooleanโ€”Close when a menu entry is clicked. Default `true`.
closeOnOutsideClickbooleanโ€”โ€”
closeOnEscapebooleanโ€”โ€”
cssClassButtonDropdownCssClassโ€”โ€”
cssClassNamestringโ€”โ€”