Skip to content

Switch

hc-switch is applied to a standard <input type="checkbox" role="switch">. The underlying input keeps every native behaviour — Space toggles, the value participates in form submission, screen readers announce it as a switch via the role override — and only the visual chrome is replaced via appearance: none.

.hc-switch-label is an inline-flex helper that clusters the switch and its text so a click on the label toggles the input.

data-variant accepts success, warning, and error for non-default checked-state tints — the same trio as checkbox and radio. The default (omitted) variant uses the active color theme’s primary fill.

data-size accepts sm, md (default), and lg.

The switch participates in form submission like any native checkbox. For instant toggles, listen to change:

<label class="hc-switch-label">
<input
class="hc-switch"
type="checkbox"
role="switch"
name="notifications"
data-hx-post="/preferences/notifications"
data-hx-trigger="change">
Email notifications
</label>

When the switch is part of a plain form post and the server binds a declared boolean, remember that an unchecked switch submits nothing — use the blessed boolean-field pattern (hidden false + switch true under one name); it applies to hc-switch verbatim.

  • Always pair the input with a label. Either wrap both in <label class="hc-switch-label"> or use a separate <label for> associated by id.
  • role="switch" is the semantic role for a binary on/off toggle — prefer it over a plain checkbox so screen readers announce “switch, on/off” rather than “checkbox, checked/unchecked”. The underlying element stays an <input type="checkbox"> for form serialisation; the ARIA role override only changes how it’s announced.
  • Don’t remove the focus outline. The component replaces the default outline with a visible box-shadow ring driven by --hc-color-focus-ring.
  • The thumb-slide transition respects prefers-reduced-motion: reduce — motion is suppressed when the user has opted out.

Component tokens (in component.tokens.json):

Token pathPurpose
switch.width / heightTrack dimensions.
switch.thumb-sizeDiameter of the moving thumb.
switch.paddingGap between thumb and track edge.
switch.bg / thumb-bgOff-state colors.
switch.checked-bg / checked-borderDefault-variant on-state.
switch.success-checked-bg / error-checked-bgVariant on-state.
switch.disabled-bgBackground when disabled.
switch.label-gapGap between switch and its text.
switch.sm.* / lg.*Dedicated sm / lg overrides.
Show the generated CSS variables
--hc-switch-width | -height | -thumb-size | -padding
--hc-switch-border-width | -border
--hc-switch-bg | -thumb-bg
--hc-switch-checked-bg | -checked-border
--hc-switch-success-checked-bg | -error-checked-bg
--hc-switch-disabled-bg | -label-gap
--hc-switch-sm-width | -sm-height | -sm-thumb-size
--hc-switch-lg-width | -lg-height | -lg-thumb-size
--hc-color-focus-ring (inherited from data-color)
  • Checkbox — when the metaphor is “agree / opt-in” rather than “turn this on/off”.
  • Radio — single pick from a small fixed set.