Buttons

A group of buttons: a wrapping row, or one joined control with data-affix.

Example

View Code
<div class="buttons" role="group" aria-label="Text style" data-affix>
    <button class="button" type="button" data-emphasis="medium" aria-pressed="true">Bold</button>
    <button class="button" type="button" data-emphasis="medium" aria-pressed="false">Italic</button>
    <button class="button" type="button" data-emphasis="medium" aria-pressed="false">Underline</button>
</div>
<fieldset>
    <legend>Billing</legend>
    <div class="buttons" data-affix>
        <label class="button" data-emphasis="medium"><input type="radio" name="example-billing" value="monthly" checked> Monthly</label>
        <label class="button" data-emphasis="medium"><input type="radio" name="example-billing" value="yearly"> Yearly</label>
    </div>
</fieldset>

When to use it

Two or more buttons that belong together: a form's submit and cancel, a set of view toggles, a toolbar row. Loose, they sit in a row at a small gap and wrap when they must. Affixed, they become one control with shared borders, the shape of a segmented toggle.

How it works

Loose is a wrapping flex row at data-gap. data-affix removes the gap, squares the inner corners, and overlaps each border with the next so the seam is one line wide. A focused member is lifted above its neighbours so its focus ring is not covered. An affixed group is one control, so it never wraps onto a second row: short of room, its members narrow and their labels wrap inside them.

<div class="buttons" role="group" aria-label="Form actions">
    <button class="button" type="submit">Save</button>
    <button class="button" type="button" data-emphasis="low">Cancel</button>
</div>

A segmented control, one choice of several, is an affixed group of label.button members wrapping radios that share one name, inside a fieldset whose legend names it. The checked one is filled, the arrow keys move the choice, and it submits with the form, all with no script. The fieldset is the named group here, so the div inside it needs no role or label of its own.

<fieldset>
    <legend>Billing</legend>
    <div class="buttons" data-affix>
        <label class="button" data-emphasis="medium"><input type="radio" name="billing" value="monthly" checked> Monthly</label>
        <label class="button" data-emphasis="medium"><input type="radio" name="billing" value="yearly"> Yearly</label>
    </div>
</fieldset>

A row of real <button aria-pressed> members draws the same way; it suits a toolbar where each button acts at once, but moving aria-pressed from one member to the next is your script's job.

Accessibility

The group carries role="group" and a name, so a screen reader announces the set once. A segmented control of radios inside a fieldset is named by its legend and announced as radio buttons, one checked; a toggle of buttons puts aria-pressed on each and the pressed look follows. Do not use an affixed group as tabs; tabs have their own roles and keyboard behaviour and are a separate component.

Attributes

Attribute Type Values Default Description
data-gap enum none, xs, sm, md, lg, xl, 2xl, 3xl, xs-sm, xs-md, xs-lg, xs-xl, xs-2xl, xs-3xl, sm-md, sm-lg, sm-xl, sm-2xl, sm-3xl, md-lg, md-xl, md-2xl, md-3xl, lg-xl, lg-2xl, lg-3xl, xl-2xl, xl-3xl, 2xl-3xl sm Space between buttons when not affixed.
data-affix boolean Join the buttons into one segmented control that shares borders.

Children

  • > .button: at least 2. The buttons.

Tokens

Token Description
--yeti-space-sm The default gap.
--yeti-border-width The width the joined members overlap by.
Internal tokens (may change between minor versions) - `--_yeti-gap`

Accessibility

  • Role: group
  • Required attributes: role, aria-label or aria-labelledby
  • role="group" with a name, so the set is announced as one thing. Inside a fieldset with a legend the fieldset is the named group and the div needs neither. A segmented control is label.button members wrapping radios that share one name, inside such a fieldset: the arrow keys move the choice natively. A toggle of buttons sets aria-pressed on each member and needs a script to move it; a set of tabs is the tabs component, not this.
Key Action
Arrow keys In a segmented control of radios, move the choice to the previous or next option.

Browser support

  • Used without guards: flexbox gap, logical border radii
  • Behind @supports: nothing

JavaScript

None. This component is CSS only.

Available since 7.0.0.