Checkbox
hc-checkbox is applied to a standard <input type="checkbox">. The
underlying input keeps every native behaviour — Space toggles, the
value/name participate in form submission, screen readers report it as
a checkbox. Only the rendering is replaced via appearance: none.
Basic HTML
Section titled “Basic HTML”Send me product updates
Subscribe to the newsletter
<label class="hc-checkbox-label"> <input class="hc-checkbox" type="checkbox" checked> Send me product updates</label>
<label class="hc-checkbox-label"> <input class="hc-checkbox" type="checkbox"> Subscribe to the newsletter</label>.hc-checkbox-label is a thin inline-flex helper that clusters the
input and its text and propagates click behaviour. You can also use a
bare <input class="hc-checkbox"> next to a separate <label for>
element.
Variants
Section titled “Variants”data-variant accepts success, warning, and error for
non-default check colors. The default (omitted) variant uses the
active color theme’s primary fill.
Default (themed)
Success
Warning
Error
<input class="hc-checkbox" type="checkbox" checked><input class="hc-checkbox" type="checkbox" data-variant="success" checked><input class="hc-checkbox" type="checkbox" data-variant="warning" checked><input class="hc-checkbox" type="checkbox" data-variant="error" checked>data-size accepts sm, md (default), and lg. Independent of
data-density — sizes set dedicated --hc-checkbox-{sm,lg}-size
vars rather than overriding the density-aware default size, so a
control that opts in with data-size="sm" stays at 14 px on every
density tier.
Small
Default
Large
<input class="hc-checkbox" type="checkbox" data-size="sm" checked><input class="hc-checkbox" type="checkbox" checked><input class="hc-checkbox" type="checkbox" data-size="lg" checked>data-size | Outer dimension |
|---|---|
sm | 0.875rem (14 px) |
md | 1.125rem (18 px) — default |
lg | 1.375rem (22 px) |
States
Section titled “States”Focus me to see the ring
Required field (aria-invalid)
Disabled (unchecked)
Disabled (checked)
<input class="hc-checkbox" type="checkbox" aria-invalid="true"><input class="hc-checkbox" type="checkbox" disabled><input class="hc-checkbox" type="checkbox" disabled checked>The indeterminate state (set in JS via input.indeterminate = true)
renders as a small horizontal bar in place of the check mark.
As a boolean form field
Section titled “As a boolean form field”An unchecked checkbox submits nothing — a server binding a declared
boolean input from a form post sees an absent field instead of false.
This is the blessed boolean-field pattern: a hidden input that
guarantees a value, paired with the checkbox under the same name,
inside an hc-field stanza.
It is plain markup — code generators can emit it verbatim for boolean
columns, and it is stable under the
markup versioning policy.
<div class="hc-field"> <label class="hc-field__label" for="active">Active</label>
<!-- Unchecked submits nothing — the hidden input guarantees `active=false`. It must come first: when the checkbox is checked, both submit and the server takes the last value. --> <input type="hidden" name="active" value="false"> <input class="hc-checkbox" id="active" name="active" type="checkbox" value="true">
<p class="hc-field__message">Deactivated accounts are hidden from search.</p></div>The contract: unchecked submits active=false; checked submits
active=false&active=true, and the server binds the last
occurrence — the convention mainstream form binders follow (it is how
Rails’ check_box helper has worked for years). Keep the hidden input
first in the DOM; document order is what makes last-wins work.
Which label pattern
Section titled “Which label pattern”Inside an hc-field stanza use hc-field__label + for, exactly as
above — it keeps the label column consistent with every other field
type. The .hc-checkbox-label cluster is for checkboxes outside a
field stanza: a standalone consent line, or the items of a
<fieldset class="hc-field"> group.
Switch variant
Section titled “Switch variant”hc-switch is literally
<input type="checkbox" role="switch"> — it participates in form
submission identically, so the pattern transfers verbatim:
<div class="hc-field"> <label class="hc-field__label" for="notify">Email notifications</label> <input type="hidden" name="notify" value="false"> <input class="hc-switch" id="notify" name="notify" type="checkbox" role="switch" value="true"></div>Field errors
Section titled “Field errors”The field-errors recipe
works unchanged: a server item with data-field="active" resolves the
same-name group and wires the message, aria-invalid, focus, and
edit-to-clear to the checkbox — hidden members of a group are
skipped, so the duplicated name never confuses the distribution.
These claims are pinned by a browser test against this exact markup
(test-browser/booleanfield.spec.mjs), so the pattern stays stable for
generated code.
htmx usage
Section titled “htmx usage”hc-checkbox participates in form submissions like any native checkbox.
For server-side validation feedback, return the input with
aria-invalid="true" set; pair with hc-field
to also restyle the surrounding message.
<label class="hc-checkbox-label"> <input class="hc-checkbox" type="checkbox" name="terms" required data-hx-post="/preferences/toggle" data-hx-trigger="change"> I accept the terms</label>Accessibility
Section titled “Accessibility”- The component preserves the native
<input type="checkbox">, so assistive tech announces it correctly andSpacetoggles it. - Always associate the input with a label. The easiest pattern is to
wrap both in a
<label class="hc-checkbox-label">. Otherwise use a separate<label for>linked to the input’sid. - For validation errors set
aria-invalid="true"on the input. Pair witharia-describedbyif you have an error message. - Prefer the native
disabledattribute when the control must not be interactive. Usearia-disabled="true"only when it must remain focusable. - Do not remove the focus outline. The component replaces the default
outline with a visible box-shadow ring driven by
--hc-color-focus-ring.
Theming tokens
Section titled “Theming tokens”Component tokens (in component.tokens.json):
| Token path | Purpose |
|---|---|
checkbox.size | Outer dimension (square). |
checkbox.border / border-width / radius | Border in the unchecked state. |
checkbox.bg | Background in the unchecked state. |
checkbox.checked-bg / checked-border | Default-variant checked colors. |
checkbox.success-checked-bg / success-checked-border | data-variant="success". |
checkbox.warning-checked-bg / warning-checked-border | data-variant="warning". |
checkbox.error-checked-bg / error-checked-border | data-variant="error". |
checkbox.sm.size / lg.size | data-size="sm" / "lg" dedicated sizes. |
checkbox.error-border | Border when aria-invalid="true". |
checkbox.disabled-bg | Background when disabled. |
checkbox.label-gap | Gap between the input and its text. |
CSS variables
Section titled “CSS variables”Show the generated CSS variables
--hc-checkbox-size--hc-checkbox-border-width | -border | -radius--hc-checkbox-bg--hc-checkbox-checked-bg | -checked-border--hc-checkbox-success-checked-bg | -success-checked-border--hc-checkbox-warning-checked-bg | -warning-checked-border--hc-checkbox-error-checked-bg | -error-checked-border--hc-checkbox-sm-size | -lg-size--hc-checkbox-error-border--hc-checkbox-disabled-bg--hc-checkbox-label-gap--hc-color-focus-ring--hc-color-error