Skip to content

ButtonGroup & split buttons

A ButtonGroup puts several actions behind one control. It comes in two shapes:

  • a dropdown — one trigger, labelled with the group’s label, that opens the group’s buttons;
  • a split button — a group with a primary: the primary action runs from the button itself, and an adjacent ▾ opens the other buttons. Use it when one action is the usual one and the rest are variants of it (“Save” + “Save as draft”, “Save and close”).

A group sits wherever a button does: a page or form toolbar, a form’s buttons, a listing toolbar and plain content. Every button in it keeps its own actionId (or handler, or route) and runs exactly as it would on its own.

// a dropdown
ButtonGroup.of("Export",
new Button("CSV", "exportCsv"),
new Button("PDF", "exportPdf"));
// a split button: "Save" runs from the button, the rest is behind its ▾
ButtonGroup.split(
Button.builder().label("Save").actionId("save").buttonStyle(ButtonStyle.primary).build(),
new Button("Save as draft", "saveAsDraft"),
new Button("Save and close", "saveAndClose"));
// or with the builder
ButtonGroup.builder()
.primary(new Button("Save", "save"))
.buttons(List.of(new Button("Save as draft", "saveAsDraft")))
.build();

Put them in a Form’s toolbar/buttons, a listing’s toolbar, or any layout’s content. A button with its own handler (callable/runnable) inside a group is advertised and runs like any other fluent handler button.

@Toolbar (and @Button) methods sharing a group collapse into one dropdown labelled with the group’s name. Mark one member groupPrimary = true and the group becomes a split button instead:

@Toolbar(group = "save", groupPrimary = true, buttonStyle = ButtonStyle.primary, order = 1)
public Message save() { … }
@Toolbar(group = "save", order = 2)
@Label("Save as draft")
public Message saveAsDraft() { … }
@Toolbar(group = "export", order = 3) public void csv() { … } // the "Export" dropdown
@Toolbar(group = "export", order = 4) public void pdf() { … }

order fixes the sequence (reflection does not keep the declaration order); the group takes the place of its first member. Several members claiming groupPrimary: the first wins.

toolbar:
- type: ButtonGroup # a split button: it has a primary
primary: {type: Button, label: Save, actionId: save, buttonStyle: primary}
buttons:
- {type: Button, label: Save as draft, actionId: saveAsDraft}
- type: ButtonGroup # a dropdown
label: Export
buttons:
- {type: Button, label: CSV, actionId: exportCsv}
- {type: Button, label: PDF, actionId: exportPdf}
PropertyTypeDescription
idStringOptional component id
labelStringThe dropdown’s trigger text (not drawn on a split button)
iconOnLeft / iconOnRightStringThe dropdown trigger’s icons
separatorBeforebooleanA separator before the group in a toolbar
buttonsList<Button>The buttons behind the trigger / the ▾
primaryButtonSet: a split button whose button runs this action
RendererDropdownSplit button
Vaadinvaadin-menu-bar with one itemone vaadin-menu-bar: the primary + a ▾ item named “More actions” (←/→ between the parts, ↓/Enter opens the menu, Esc closes it)
Redwoodits buttons in the row / the Spectra header’s actionsin content oj-button + an icon-only oj-menu-button (“More actions”); in the page header the primary first, then the rest (Spectra’s header has its own primary slot and overflow)
React Nativea button opening a Paper Menua Paper button + a ▾ button (“More actions”) opening a Menu
Desktop (IntelliJ)a “label ▾” button with a popup menua JButton + a ▾ button (“More actions”, ↓ opens) with a popup menu; the native host toolbar lists the primary then the rest

On the wire a group is a Button whose children are its buttons; a split button is the primary button itself with split: true (see the wire specification).

  • .NET — Button.Group("Export", …) / Button.Split(primary, …) (a Button carrying Buttons), and [Toolbar(Group = "save", GroupPrimary = true)].
  • Python — Button.group("Export", …) / Button.split(primary, …), and @toolbar(group="save", group_primary=True).

The three backends emit the same wire (conformance case button-groups).

See it live in the Explorer: Button, ButtonGroup & split buttons