Checkbox
A labeled checkbox with description, inline error, and an indeterminate state for select-all patterns.
Import
import { Checkbox } from "@hyzer-labs/ui"Demo
Checkbox vs Toggle
Checkbox when selecting from a list, building multi-select membership, or
driving the indeterminate select-all pattern. For a single on/off setting that reads like a
switch, use Toggle instead.let ace = $state(false);
<Checkbox name="ace" label="Hit an ace this round" bind:checked={ace} />indeterminate is visual and announced state only, so checked is
unaffected. In the select-all pattern the parent is never bound: its state is derived from
the children, and toggling it rewrites them. Try it live.
let notify = $state({ leagues: true, tournaments: false, courses: false });
const allOn = $derived(Object.values(notify).every(Boolean));
const someOn = $derived(Object.values(notify).some(Boolean));
<Checkbox
name="notify-all"
label="All notifications"
checked={allOn}
indeterminate={someOn && !allOn}
onchange={setAll}
/>
<Checkbox name="notify-leagues" label="League nights" bind:checked={notify.leagues} />
<Checkbox name="notify-tournaments" label="Tournaments" bind:checked={notify.tournaments} />
<Checkbox name="notify-courses" label="Course updates" bind:checked={notify.courses} />description and error are announced with the field: both chain
into aria-describedby. Error and disabled are also field states, and the
wrapper's data-state reflects them, with error winning.
Spotters watch the water carry and mark landing positions.
You must accept the waiver to play.
<Checkbox
name="spotter"
label="I can spot on hole 18"
description="Spotters watch the water carry and mark landing positions."
/>
<Checkbox name="waiver" label="Accept the liability waiver" error="You must accept the waiver to play." />
<Checkbox name="rules" label="I've read the tournament rules" required />
<Checkbox name="cart" label="Cart rental (sold out)" disabled />
<Checkbox name="fee" label="Entry fee paid" disabled checked />Props
| Name | Type | Default | Note |
|---|---|---|---|
name | string | — | Required. Form field name. |
label | string | — | Required. Always in the DOM; sr-only with hideLabel. |
checked | boolean | false | Bindable. |
indeterminate | boolean | false | Set via the DOM .indeterminate property; visual only, checked is unaffected. |
value | string | — | Submitted value when checked. |
description | string | — | Help text below the label. |
error | string | — | Inline error message; sets the error state. |
required | boolean | false | |
disabled | boolean | false | |
hideLabel | boolean | false | |
class | string | — | Merged after the hz-field hz-field--checkbox classes. |
Theme hooks
What this component promises your CSS. The reference theme styles exactly these — from @layer hz-theme, so your unlayered rules win. See Styling Components for the how.
Root class: .hz-field hz-field--checkbox
Data attributes
| Hook | Values | Styles |
|---|---|---|
data-state | 'default' | 'error' | 'disabled' | The universal field state hook, on the root. Precedence is fixed: error beats disabled. |
:checked / :indeterminate | native pseudo-classes | Checkbox stamps no attribute for either — style the native pseudo-classes. (indeterminate is set as a DOM property, so only :indeterminate sees it.) |
Part classes
| Hook | Values | Styles |
|---|---|---|
.hz-field-label | child element | The label. |
.hz-field-required | child element | The required marker. |
.hz-field-description | child element | The hint text. |
.hz-field-error | child element | The error message. |
Accessibility
The input is associated with its label via id/for (the label renders after the box). description and error chain into aria-describedby, description first. required sets aria-required, and an error sets aria-invalid.
indeterminate is applied through the DOM .indeterminate property, so screen readers announce the mixed state natively.
References: APG Checkbox pattern · MDN: <input type="checkbox">