Prototype Library

Button toggle

A segmented single-select — one-of-N choices rendered as a row of connected buttons. Form-associated, holds the selected value, and follows the WAI-ARIA radiogroup pattern with arrow-key navigation.

Inheritedwcimport '@esa/ecology/esa-button-toggle';

Preview

<esa-button-toggle label="View" id="bt-preview"></esa-button-toggle>

<script>
  el.options = [
    { value: 'list', label: 'List' },
    { value: 'grid', label: 'Grid' },
    { value: 'map', label: 'Map' },
  ];
  el.value = 'grid';
</script>

Sizes

Four sizes share the form scale. Default is md.

<esa-button-toggle size="xs"></esa-button-toggle>
<esa-button-toggle size="sm"></esa-button-toggle>
<esa-button-toggle size="md"></esa-button-toggle>
<esa-button-toggle size="lg"></esa-button-toggle>

States

<esa-button-toggle label="Default"></esa-button-toggle>
<esa-button-toggle label="Disabled" disabled></esa-button-toggle>

Form participation

The control submits its selected value under its name. Submitting logs the view entry.

<form>
  <esa-button-toggle name="view" label="View"></esa-button-toggle>
  <button type="submit">Submit</button>
</form>

API

PropTypeDefaultDescription
options{ value: string, label: string }[][]The segments. Set as a property (it is an array, not an attribute).
valuestring''Selected option's value. Single-select; bound to the form value.
labelstring''Optional visible label above the group; becomes the radiogroup name.
size'xs' | 'sm' | 'md' | 'lg''md'Control size (shared form scale).
requiredbooleanfalseMarks the field required (adds an asterisk and aria-required).
disabledbooleanfalseDisables every segment.

Events

EventTypeDefaultDescription
changeCustomEvent<{ value: string }>—Fired when the selection changes. Composed and bubbling; detail.value is the newly selected value.

Accessibility

  • Renders role="radiogroup" wrapping role="radio" buttons with aria-checked reflecting selection.
  • Roving tabindex: only the selected (or first) segment is tab-reachable; Arrow keys move selection through the group, wrapping at the ends.
  • Home and End jump to the first and last segments; Enter and Space select the focused segment.
  • The label becomes the group's accessible name via aria-labelledby.
  • Visible focus ring on the active segment via --focus-ring-* tokens; the focused segment is raised so its ring sits above neighbors.
  • Best for small fixed option sets — past about six options, prefer a select.

Tokens

Override the form and semantic token layers to re-skin without touching the component:

  • --color-background-brand · --color-content-default-knockout — selected segment fill and text
  • --form-{height,padding-x,font-size,radius}-{xs,sm,md,lg} — size scale
  • --color-background-field · --form-border-color · --form-text-color — unselected segments
  • --color-background-elevation-sunken — hover tint · --color-content-disabled — disabled state
  • --focus-ring-width / --focus-ring-color — focus ring
  • --form-label-color — label