Skip to content

BbDropdownButton

A split button for one frequent action and a short menu of close alternatives.

import { BbDropdownButton } from 'bitboss-ui';

On this page

Use it for

Use BbDropdownButton when one action is frequent and the menu contains close alternatives: Save / Save as draft, Export / Export as CSV, Merge / Squash.

Use something else when

Also see: Options and items.

Its item model comes from BbDropdown; variants and sizes come from BbButton.

Passthrough

Hover or tap a part to outline it. The toggles turn on loading, errors and warnings where the component has them; only parts get a row.

Put the frequent action first

The component is the main button: its label is the default slot, and @click, href / to, type / form, loading, disabled and the icons work exactly as on a BbButton. items is only the menu that opens from the chevron.

Unsaved changes

  • Every item is a menu row, with BbDropdown's item model, so groups, submenus, links and descriptions all work there.
  • A list that comes down to nothing can stay on the component: with no items (and no #dropdown slot) the chevron goes and it renders exactly like a BbButton.
  • In a form, write type="submit" (and form="id" from outside it) on the component: the main button submits the BbForm and spins while its save runs, like a submit BbButton. Menu rows stay plain actions.
  • Navigation goes on href / to, the component's or a row's, never in a click handler.
Coming from v2items[0] → the component

Up to beta.57, items[0] became the main button. It is now the first menu row. Move it onto the component: its label becomes the default slot, its onClick the component's @click, its href / to / type / form / disabled the component's props. npx bitboss-ui check flags a split button with no label.

diff
- <BbDropdownButton :items="[{ value: 'save', label: 'Save', onClick: save }, ...alternates]" />
+ <BbDropdownButton :items="alternates" @click="save">Save</BbDropdownButton>

Keep both halves coherent

Set variant, size, block and icons on the component: both halves take them, so they never disagree.

primary
secondary
outline
ghost
destructive
link
xs
sm
md
lg
xl
2xl
block

Every BbButton variant and size applies, destructive and link included. toggle:icon replaces only the toggle chevron. The #icon, #prepend:icon and #append:icon slots belong to the main button, as on BbButton: they swap its glyph with its states (loading, activeLink, …), inside its icon part.

To start a style from scratch, variant="none" gives both halves a blank base and your classes draw the rest; you own the hover, the focus ring and the disabled look. Reach each half with pt:main and pt:toggle. (On Tailwind v4 your classes win over the button's own rules only with cssLayers set.)

Draft · last edited 10:42

When the look recurs, register it as a variant: buttonVariants names are valid here too. When the trigger is not a button at all, build it from BbBaseButton and BbDropdown.

Coming from v2theme → variant

theme is removed; use variant. arrowPadding is also removed because the menu has no arrow.

Return promises from actions

When the component's @click returns a promise, the main button shows loading and blocks re-entry; a menu row's async onClick does the same to the toggle.

Draft

Use loading only for external work. disable-auto-loading opts the main action out; menu actions still drive the toggle.

Coming from v2autoLoading → disableAutoLoading

The prop was renamed with inverted polarity. disabledWhileLoading is removed; busy halves are always disabled.

Gate dangerous alternatives

Keep irreversible work behind the toggle, mark it destructive and await confirmation before acting.

vantera-web · production

dpl_7k2f · deployed 08 Jul 2026

The confirm renders in the app's one <BbHost />, mounted at the root; a page with a split button mounts nothing.

Let the menu configure the action

A selectable group in the menu can parameterise the main action. Make the label follow the selection, so it always states what pressing it will do.

2 approvals · all checks passed

Bind the group with a <BbDropdownGroup> companion in the #dropdown slot: the default slot is the label. The menu's item:selected and item:unselected reach the split button, so listen there for the moment of a change.

Menu slots, placement props, compact, adaptive and off-canvas-props forward to the inner dropdown: every slot but the label (default), #dropdown and activator.

item:prepend decorates the menu rows only; the main button's icon is its own prepend:icon. pt:header and pt:footer style the bands around those two slots, on the flyout and the phone sheet alike. The menu aligns to the whole split control; trigger, anchor and boundary are not exposed, so use BbDropdown directly when one of them is required.