v1.0.0

<bmx-button-group>

Three widgets in one tag, because they differ only in bookkeeping:

14 properties · 1 events · 2 methods · 1 parts

Example

List Grid Board
Cut Copy Paste Undo
Show markup
<div class="row">
  <bmx-button-group label="View mode" selection="single" value="grid" attached="true" variant="outline" tone="neutral">
    <bmx-button value="list">List</bmx-button>
    <bmx-button value="grid">Grid</bmx-button>
    <bmx-button value="board">Board</bmx-button>
  </bmx-button-group>
</div>
<div class="row">
  <bmx-button-group label="Document actions" attached="true" variant="outline" tone="neutral">
    <bmx-button>Cut</bmx-button>
    <bmx-button>Copy</bmx-button>
    <bmx-button>Paste</bmx-button>
    <bmx-button disabled="true">Undo</bmx-button>
  </bmx-button-group>
</div>

selection="none" a toolbar - related actions, visually joined selection="single" a segmented control - one of N, like a view switcher selection="multiple" a set of independent toggles, like text formatting

WHY THE GROUP OWNS THE KEYBOARD

Eight individually tabbable buttons cost a keyboard user eight Tab presses to skip. WAI-ARIA's composite-widget pattern gives the group one Tab stop and moves within it on the arrow keys - which is also how the native radio group and <select> that the user already knows behave.

That requires taking the non-active children out of the tab order, and the focusable element inside a bmx-button lives in a shadow root the group cannot reach. Hence rovingTabindex on the child: the group decides, the child applies. Plain <button> children are supported too - they get their tabIndex set directly - so a consumer can mix in their own markup.

WHY aria-pressed RATHER THAN role="radio" FOR SINGLE SELECTION

A radio group announces "radio button, 2 of 5", which is right for a form question and wrong for a view switcher that acts immediately. Toggle buttons announce "pressed", which is what a segmented control actually is. Both are conformant; this one matches what the control does.

Properties

PropertyAttributeTypeDefaultDescription
attached attached boolean false Join the buttons into one continuous control, sharing their borders.
disabled disabled boolean false Disable every child. Children may still be disabled individually.
fullWidth full-width boolean false Stretch the group, and its children equally, to the container width.
label label string The group's accessible name. Not optional in practice: a toolbar announced as "group" with no name tells a screen reader user only that something has been grouped. Pass what the group is for - "Text alignment", "View mode".
orientation orientation BmxOrientation 'horizontal' Layout direction. Also decides which arrow keys move focus.
selection selection BmxButtonGroupSelection 'none' How many items may be selected.
shape shape BmxShape Applied to every child that has not set its own.
size size BmxSize Applied to every child that has not set its own.
tone tone BmxTone Applied to every child that has not set its own.
value value string | null null The selected value, in single mode. Two-way: the group writes back to it.
values property only string[] [] The selected values, in multiple mode. Two-way. Accepts a comma-separated or JSON string as well, because an attribute is the only channel some templates have. See src/core/markup.ts.
variant variant BmxButtonVariant Applied to every child that has not set its own.
wrap wrap boolean false Allow the group to wrap onto more than one line.
wrapFocus wrap-focus boolean true Whether arrowing past the last item returns to the first.

Events

EventDetailDescription
bmxChange BmxButtonGroupChangeDetail Fired when the selection changes. Not fired in selection="none".

Methods

MethodSignatureDescription
refresh refresh() => Promise<void> Re-read the children. Call after adding or removing items imperatively.
setFocus setFocus() => Promise<void> Move focus to the group's active item.

Slots

SlotDescription
(default) bmx-button elements, or any focusable controls.

CSS shadow parts

PartDescription
base The group container.

CSS custom properties

PropertyDescription
--bmx-button-group-gap Space between items when the group is not attached.