Prototype Library

Checkbox Group

Multi-select from an options list; the value is a string[]. Vertical or horizontal orientation, per-option disabled, Space/Enter toggling. The options attribute accepts a JSON string. Emits a composed change event.

Inherited wc import '@esa/ecology/esa-checkbox-group';

Preview

<esa-checkbox-group
  label="Monitored media"
  options='[{"label":"Air quality","value":"air"}, …]'
  value='["water"]'
></esa-checkbox-group>

Orientation

vertical is the default; switch to horizontal to lay options out in a row.

<esa-checkbox-group label="Monitored media" orientation="horizontal" options="…"></esa-checkbox-group>

Sizes

<esa-checkbox-group label="Extra small" size="xs" orientation="horizontal" options="…"></esa-checkbox-group>
<esa-checkbox-group label="Small" size="sm" orientation="horizontal" options="…"></esa-checkbox-group>
<esa-checkbox-group label="Medium" size="md" orientation="horizontal" options="…"></esa-checkbox-group>
<esa-checkbox-group label="Large" size="lg" orientation="horizontal" options="…"></esa-checkbox-group>

Form participation

Each selected value is submitted under name. Submitting logs all media entries.

<form>
  <esa-checkbox-group label="Media" name="media" options="…" value='["air"]'></esa-checkbox-group>
  <button type="submit">Submit</button>
</form>

API

PropTypeDefaultDescription
options EsaOption[] [] Array of {'{ label, value, disabled? }'}, or a JSON string of the same when set as an attribute.
label string '' Group label rendered above the options.
size 'xs' | 'sm' | 'md' | 'lg' 'md' Box and label size.
orientation 'vertical' | 'horizontal' 'vertical' Stacking direction of the options.
name string | undefined — Field name each selected value is submitted under.
value string[] [] Selected option values.
required boolean false Whether at least one option must be chosen. Unlike esa-radio-group this canNOT use `aria-required`: a checkbox group is a `group`, and ARIA only allows aria-required on widget roles like `radiogroup`. Overriding the role to radiogroup would be a lie — radiogroup means single-select. So the requirement goes where the spec's own technique (H90) puts it: in the group's ACCESSIBLE NAME, as "(select at least one)" appended to the legend.
help-text string '' Property: `helpText`.
error-text string '' Validation message below the group; reddens the legend and renders the error line. Property: `errorText`.
live-error boolean false Announce the error the moment it appears rather than only when the group is entered. Off by default — see the long note on `esa-text-field.liveError`. Property: `liveError`.

Events

EventTypeDefaultDescription
change CustomEvent<{ value: string[] }> — Fired when any option is toggled. Composed and bubbling; detail.value is the current selection array.
Binding these events from Angular

Every one of these is a CustomEvent, so the payload is on $event.detail — $event.target.value reads empty, with no error. The names are lowercase and Angular passes them to addEventListener verbatim, so camel-casing one means it never fires.

  • (change)="onChange($event.detail)"

Accessibility

  • The options container has role="group", named by aria-label from the label attribute — so leaving label unset leaves the group unnamed. Note that role="group" has weak support on iOS VoiceOver and Android TalkBack; a native <fieldset>/<legend> is the more reliable grouping.
  • Each box has role="checkbox" with aria-checked and toggles on Space or Enter.
  • Known gaps. The option text sits in a sibling <span>, and a wrapping <label> cannot name a <span role="checkbox"> — options currently announce without their text. The click target is the box alone, not the row, so the visible text is not clickable and the target is 14–20px at xs–md, under the 24×24 minimum. esa-checkbox binds the whole row and does not have this.
  • Disabled options carry aria-disabled and a -1 tabindex.
  • The change event is composed and bubbles, so it can be caught on the host or an ancestor.