Skip to content
Home Theme Gallery

Toggle group

The custom element is <hui-toggle-group>.

Overview

A segmented control over slotted hui-toggle items, or with spacing a row of separate chips. Single mode holds one value and multiple mode holds several, with the group doing the FormData work as one repeated field.

Example

Single mode
Source
<hui-toggle-group name="style" type="single" value="b" aria-label="Text style">
<hui-toggle value="b">Bold</hui-toggle>
<hui-toggle value="i">Italic</hui-toggle>
<hui-toggle value="u">Underline</hui-toggle>
</hui-toggle-group>

The Go template that renders it:

<hui-toggle-group name="style" type="single" value="{{ .Style }}" aria-label="Text style">
<hui-toggle value="b">Bold</hui-toggle>
<hui-toggle value="i">Italic</hui-toggle>
<hui-toggle value="u">Underline</hui-toggle>
</hui-toggle-group>

On a phone

Joined toggles are one segmented control and scroll inside their border when they do not fit. Spaced chips (spacing) are separate controls, so they wrap onto more lines instead.

Joined scrolls, spaced wraps 375 px wide
Source
<hui-toggle-group name="day" type="multiple" aria-label="Days">
<hui-toggle value="monday">Monday</hui-toggle>
<hui-toggle value="tuesday">Tuesday</hui-toggle>
<hui-toggle value="wednesday">Wednesday</hui-toggle>
<hui-toggle value="thursday">Thursday</hui-toggle>
<hui-toggle value="friday">Friday</hui-toggle>
<hui-toggle value="saturday">Saturday</hui-toggle>
</hui-toggle-group>
<p style="margin:1rem 0 .5rem;font-size:.875rem">Spaced:</p>
<hui-toggle-group name="scene" type="single" spacing="1" aria-label="Scene">
<hui-toggle variant="outline" value="cooking">Cooking</hui-toggle>
<hui-toggle variant="outline" value="dining">Dining</hui-toggle>
<hui-toggle variant="outline" value="focus">Focus</hui-toggle>
<hui-toggle variant="outline" value="reading">Reading</hui-toggle>
<hui-toggle variant="outline" value="movie night">Movie night</hui-toggle>
<hui-toggle variant="outline" value="away">Away</hui-toggle>
</hui-toggle-group>

API

Attributes6
Attributes
NameTypeDefaultDescription
namestring''The form field name. In multiple mode several values are appended under it.
disabledbooleanfalseDisables selection and marks every item aria-disabled.
type"single" | "multiple""single"Whether one item or several may be pressed. Reflected.
valuestring''The pressed values, comma-separated. Not reflected; the attribute only seeds the reset value.
orientation"horizontal" | "vertical""horizontal"Read by the host stylesheet to stack the items. There is no matching class field, so it affects layout only.
spacingnumber0The gap between items in steps of 0.25rem, as nova’s spacing. At 0 the items join into one segmented control; above it they stand apart and keep their own corners, so give them variant="outline" to draw each one. Reflected.
Properties5
Properties
NameTypeDefaultDescription
namestring''Reflects to the name attribute.
disabledbooleanfalseReflects to the disabled attribute.
type"single" | "multiple"'single'Reflects to the type attribute.
spacingnumber0Reflects to the spacing attribute.
valuestring''The pressed values, comma-separated. Setting it re-applies the pressed state.
Events3
Events
NameDescription
inputEmitted from the host when an item is toggled. bubbles and composed; no detail.
changeEmitted from the host in the same turn as input. bubbles and composed; no detail.
clickThe item click bubbles through the host; the group reads it and owns the selection.
Slots1
Slots
NameDescription
(default)The segments. Each must be a hui-toggle or match [role="button"][aria-pressed], and carry its value.
CSS custom properties3
CSS custom properties
NameDefaultDescription
--hui-borderoklch(0.922 0.005 325.62)The shared outline and the divider between segments.
--hui-radius0.45remBase radius; the group uses --hui-radius-lg.
--hui-focus-ring-width3pxWidth of the keyboard focus ring.
::part() hooks1
::part() hooks
NameDescription
groupThe wrapper that carries role="group". Segmented, it draws the single shared border and the outer radius; spaced, it draws neither and sets the gap.

States

Multiple

type="multiple" lets several items be down at once, and the value is the pressed items in a comma-separated list.

Multiple
Source
<hui-toggle-group name="features" type="multiple" value="x,y" aria-label="Features">
<hui-toggle value="x">X</hui-toggle>
<hui-toggle value="y">Y</hui-toggle>
<hui-toggle value="z">Z</hui-toggle>
</hui-toggle-group>

Spaced outline chips

spacing breaks the segmented control into separate chips. Chips wrap onto another line when they do not fit, where a joined group scrolls.

Spaced outline chips
Source
<hui-toggle-group name="scene" type="single" spacing="1" aria-label="Scene">
<hui-toggle variant="outline" value="cooking" pressed>Cooking</hui-toggle>
<hui-toggle variant="outline" value="dining">Dining</hui-toggle>
<hui-toggle variant="outline" value="focus">Focus</hui-toggle>
</hui-toggle-group>

Disabled

Disabled: the whole group, including the item that is down.

Disabled
Source
<hui-toggle-group name="style" type="single" value="b" disabled aria-label="Text style">
<hui-toggle value="b">Bold</hui-toggle>
<hui-toggle value="i">Italic</hui-toggle>
</hui-toggle-group>

Server-side mechanics

The server owns name, type, value, disabled and the slotted hui-toggle items with their value and pressed. In single mode it submits one value under name; in multiple mode it appends one entry per pressed value under the same name, which a Go handler reads as a repeated field. Because value is not reflected and the group reads the items, an hx-swap must re-render both the group's value attribute and the item markup, and a swap mid-selection drops the change. Server-rendered validation is limited to aria-invalid="true" or a hui-field invalid wrapper; the group has no required.

Accessibility

  • The wrapper is role="group"; each segment exposes aria-pressed through its own button.
  • The group sets data-grouped on every item so the shadow button squares its corners and joins the shared outline.
  • In multiple mode the group commits a FormData with one entry per pressed value under the same name, which a Go handler reads as a repeated field.
  • A disabled group refuses selection and marks items aria-disabled rather than removing them from the DOM.

Keyboard

Keyboard
KeysAction
TabEnters and leaves the group as one tab stop; one item holds tabindex="0" and the rest -1.
Arrow keysMove focus between segments, wrapping at the ends; Home and End jump to the first and last.
Space, EnterActivates the focused segment, toggling it in multiple mode and replacing the value in single mode.

Gotchas

  • There is no orientation property at all; the attribute affects layout only and no aria-orientation is exposed.
  • value is not reflected, so the pressed set must be re-seeded from the attribute (or from the items) after a swap.