Skip to content

HyToggleGroup ​

Usage examples on this page are written for Lit / plain HTML (<hy-toggle-group>). The same component ships as HyToggleGroup in @whitespaceux/harmony-react (native React 19), with typed wrappers for Angular, Solid, Svelte, and Vue. The API reference below applies to all frameworks.

A form-associated container component that manages a group of toggle buttons. Provides centralized selection state management, keyboard navigation, accessibility features, and form integration via ElementInternals API.

Toggle group, tab group or tab nav? ​

Pick by what changes, never by look. A value is picked — a view mode (list, map, grid), a density, a unit — and the same content is shown another way: a toggle group. Panels of different content switch in place: hy-tab-group. Each item is its own page and the URL changes: hy-tab-nav.

Supports two selection modes:

  • Single mode (default): Radio-group pattern — one toggle selected at a time. Arrow keys move focus and select. Uses role="radiogroup".
  • Multiple mode: Toolbar pattern — multiple toggles can be selected. Arrow keys move focus only. Space/Enter toggles selection. Uses role="toolbar".

Form Integration ​

Implements Form-Associated Custom Elements API via ElementInternals. In single mode, submits a single string value. In multiple mode, submits pipe-delimited values (e.g. "bold|italic").

Keyboard Navigation ​

  • Single mode: Arrow keys move focus and auto-select. Space selects focused item.
  • Multiple mode: Arrow keys move focus only. Space/Enter toggles focused item.
  • Home/End: Move focus to first/last item.
  • Tab: Enters/exits the group (roving tabindex).

When to use

  • Choosing one option from two to five that people switch between often: a view (list, grid), a range (day, week, month), an alignment.
  • Turning several filters of one kind on and off at once, with selection-mode="multiple".

Do

  • Order the options in a meaningful way: by size, by time or as a sequence.

When not to use

  • More than about five options: hy-select, or hy-combobox when people should type to filter.
  • Buttons that run actions and hold no selected state: a row of hy-button elements.
  • One on/off setting: hy-switch when it applies at once, hy-checkbox when a form submits it.
  • A view switcher, where one option is always shown: set disallow-empty. Leave it off for filters, where nothing selected is meaningful.

Accessibility: your part ​

  • Give every hy-toggle a name. An icon-only toggle takes aria-label.

Examples ​

Basic single selection ​

html
<hy-toggle-group value="center" label="Text alignment">
  <hy-toggle value="left">Left</hy-toggle>
  <hy-toggle value="center">Center</hy-toggle>
  <hy-toggle value="right">Right</hy-toggle>
</hy-toggle-group>

Error and warning ​

html
<!-- Not accepted: danger color, announced as an alert -->
<hy-toggle-group label="Delivery" error-message="Choose a delivery option">
  <hy-toggle value="pickup">Pickup</hy-toggle>
  <hy-toggle value="courier">Courier</hy-toggle>
</hy-toggle-group>

<!-- Accepted, but worth a second look: warning color, announced politely,
never blocks submission -->
<hy-toggle-group label="Quality" value="max" warning-message="Max quality doubles the file size">
  <hy-toggle value="standard">Standard</hy-toggle>
  <hy-toggle value="max">Max</hy-toggle>
</hy-toggle-group>

Inline layout ​

html
<style>
  .alignment-form {
    --hy-toggle-group-label-column-width: 6rem;
  }
</style>
<div class="alignment-form">
  <hy-toggle-group layout="inline" label="Alignment" value="left">
    <hy-toggle value="left">Left</hy-toggle>
    <hy-toggle value="center">Center</hy-toggle>
    <hy-toggle value="right">Right</hy-toggle>
  </hy-toggle-group>
</div>

API ​

Properties ​

PropertyAttributeTypeDefaultDescription
selectionModeselection-mode'single' | 'multiple''single'Selection mode: 'single' (radio-like) or 'multiple' (checkbox-like).
valuevaluestring''The currently selected value(s). In single mode: a single string value. In multiple mode: pipe-delimited string (e.g. "bold|italic").
orientationorientation'horizontal' | 'vertical''horizontal'Layout direction of the toggle items.
sizesize'small' | 'medium' | 'large''medium'Size of all toggle items in the group.
variantvariant'neutral' | 'brand''neutral'Visual style (role) of the toggle items.
emphasisemphasis'soft' | 'outlined''soft'Visual chrome weight propagated to every child toggle. Orthogonal to variant (role).
disableddisabledbooleanfalseDisables all toggle items in the group.
requiredrequiredbooleanfalseAt least one value must be selected for form validation.
disallowEmptydisallow-emptybooleanfalsePrevents deselecting the last selected item.
namenamestring''Form submission name.
labellabelstring''Visible group label (also sets the accessible name via aria-labelledby). Without one, aria-label / aria-labelledby on the host name the group.
helperTexthelper-textstring''Helper text below the toggle list. Replaced by error-message / warning-message while one of them shows.
errorMessageerror-messagestring''Error message below the toggle list (replaces the helper text). Setting it raises error; clearing it lowers it.
errorerrorbooleanfalseError state: the selection is not accepted and has to change. Shows error-message in the danger color. Visual and for screen readers only — form validity comes from required and setCustomValidity().
warningMessagewarning-messagestring''Warning message below the toggle list (replaces the helper text). Setting it raises warning; clearing it lowers it.
warningwarningbooleanfalseWarning state: the selection is accepted but worth a second look. Shows warning-message in the warning color; never touches form validity. error wins when both are set.
layoutlayout'block' | 'inline''block'Row layout: block (default) stacks label above the toggle list; inline puts label on the left and list on the right. Helper/error always sit under the list (col 2–end), never under the label. Set --hy-toggle-group-label-column-width on a wrapping container so stacked groups align.
fullWidthfull-widthbooleanfalseStretch the group to fill its container's inline size, distributing the toggle segments equally (flex: 1 each) — a true segmented control rather than a content-width strip. Off by design; opt in for full-bleed rows.
looploopbooleantrueWhether keyboard navigation wraps around at the edges.
form—HTMLFormElement | null—Returns the form element this group is associated with.
validity—ValidityState—Returns the ValidityState for this group.
validationMessage—string—Returns the validation message for this group.

Events ​

EventDetailDescription
change—Fired when selection changes. Detail: { selectedValues: string[], reason: 'user' | 'programmatic', name: string }
input—Standard form input event

Slots ​

SlotDescription
defaulthy-toggle elements

CSS Parts ​

PartDescription
baseOuter wrapper containing label, toggle list, and helper/error text
labelThe visible group label element
toggle-listThe container that holds the toggle items (role=radiogroup|toolbar)
helper-textHelper text below the list
error-messageError message below the list (shown while error is set)
warning-messageWarning message below the list (shown while warning is set and error is not)
message-iconThe icon starting the error or warning message

CSS Custom Properties ​

The documented hooks. Every override hook the component reads — one per token it paints — is listed in @whitespaceux/harmony/theme-api.json, and @whitespaceux/harmony/component-bindings.json (the Harmony MCP get-bindings tool) says which part and state each one paints.

PropertyDefaultDescription
--hy-toggle-group-foreground-danger-restvar(--hy-foreground-danger-rest)Error message text and icon color.
--hy-toggle-group-foreground-warning-restvar(--hy-foreground-warning-rest)Warning message text and icon color.
--hy-toggle-group-foreground-icon-default-disabledvar(--hy-foreground-icon-default-disabled)The message line's icon color when the group is disabled
--hy-toggle-group-gap-layout-2xsvar(--hy-gap-layout-2xs)Gap between the message icon and its text.
--hy-toggle-group-radius-action-mdvar(--hy-radius-action-md)Border radius for child toggle items (the action radius hy-toggle reads)
--hy-toggle-group-stroke-smvar(--hy-stroke-sm)Border width of the child toggles, which the group sets on each toggle's stroke hook and uses as the seam: neighbors overlap by it when outlined single-select, and stand apart by it when soft or multiple-select
--hy-toggle-group-gap-form-smvar(--hy-gap-form-sm)Gap between toggle items in print
--hy-toggle-group-label-column-width—Width of the label column in layout="inline" mode. No default — set on a wrapping container so stacked groups align.

Methods ​

checkValidity() ​

Checks validity against constraints.

reportValidity() ​

Checks validity and shows browser validation UI if invalid.

setCustomValidity() ​

Sets a custom validation message.

focus() ​

Sets focus on the selected toggle, or the first toggle if none selected.

Built with Lit. Documented with VitePress.