Switch
The custom element is <hui-switch>.
Overview
A binary switch sharing the checkbox wire format, so an off switch submits nothing and an on switch submits its value. It reports role="switch" so assistive technology announces it as a switch rather than a checkbox.
Example
Source
<hui-switch name="notify" value="on" aria-label="Email notifications"></hui-switch>The Go template that renders it:
<hui-switch name="notify" value="on" {{ if .Notify }}checked{{ end }} aria-label="Email notifications"></hui-switch>API
Attributes6
| Name | Type | Default | Description |
|---|---|---|---|
name | string | '' | The form field name. With no name the control contributes no entry to FormData. |
disabled | boolean | false | Disables the internal button and clears the form value. |
checked | boolean | false | The on state. Reflected. |
indeterminate | boolean | false | Inherited but ignored: a switch is binary, so no mixed style or state is drawn. |
value | string | 'on' | The value submitted while on. Reflected. |
required | boolean | false | Reflected; marks the switch required for constraint validation. |
Properties6
| Name | Type | Default | Description |
|---|---|---|---|
name | string | '' | Reflects to the name attribute. |
disabled | boolean | false | Reflects to the disabled attribute. |
checked | boolean | false | Reflects to the checked attribute. |
indeterminate | boolean | false | Reflects but is ignored by the switch rendering. |
value | string | 'on' | Reflects to the value attribute. |
required | boolean | false | Reflects to the required attribute. |
Events3
| Name | Description |
|---|---|
input | Emitted from the host after the checked flag flips. bubbles and composed; no detail. |
change | Emitted from the host in the same turn as input. bubbles and composed; no detail. |
click | The internal button click is consumed with stopPropagation(), so a native click does not cross the shadow boundary. Bind to change instead. |
CSS custom properties5
| Name | Default | Description |
|---|---|---|
--hui-primary | oklch(0.496 0.265 301.924) | Track fill while on. |
--hui-input | oklch(0.62 0.019 323.02) | Track fill while off. |
--hui-background | oklch(1 0 0) | Thumb fill. |
--hui-shadow-sm | 0 1px 2px oklch(0 0 0 / 0.05) | Thumb shadow. |
--hui-focus-ring-width | 3px | Width of the keyboard focus ring. |
::part() hooks2
| Name | Description |
|---|---|
control | The internal native <button> that carries role="switch". |
thumb | The sliding knob inside the track. |
States
On
A switch carries a name and a value and submits like a checkbox when it is on.
Source
<hui-switch name="dark" value="1" checked aria-label="Dark mode"></hui-switch>Disabled
Disabled off and on: the thumb stays where its state puts it, at half opacity.
Source
<hui-switch name="off" disabled aria-label="Disabled"></hui-switch><hui-switch name="on" checked disabled aria-label="On and disabled"></hui-switch>Server-side mechanics
The server owns name, value, checked, required and disabled. An on switch submits its value under name and an off switch submits nothing, the same wire format as a checkbox. A swap has to re-send checked to restore the on state, and a swap mid-toggle loses the flip. Server-rendered validation uses required plus aria-invalid="true" or a hui-field invalid wrapper.
Accessibility
- The internal button exposes
role="switch"witharia-checkedoftrueorfalse. - The accessible name comes from an
aria-label; a neighbouring label element does not name the shadow button. indeterminateis deliberately ignored, because a switch has only two states.- When disabled the internal button carries the native
disabledattribute and leaves the tab order.
Keyboard
| Keys | Action |
|---|---|
Tab | Moves focus to and from the switch; it is a single tab stop. |
Space, Enter | Toggles the switch. The internal native button supplies both keys. |
Gotchas
- The internal click is stopped at the shadow boundary, so a native
clicklistener on the host never fires; bind toinputorchangeinstead. indeterminateis inherited from the shared checkable base but ignored: a switch is binary, so no mixed state is drawn.