Skip to content
Home Theme Gallery

Checkbox

The custom element is <hui-checkbox>.

Overview

A form-associated checkbox in the nova treatment. An unchecked box submits nothing at all, exactly like a native checkbox, and indeterminate draws a mixed state until the next toggle.

Example

Checkbox
Source
<hui-checkbox name="agree" value="yes" aria-label="I agree"></hui-checkbox>

The Go template that renders it:

<hui-checkbox name="agree" value="yes" {{ if .Agreed }}checked{{ end }} aria-label="I agree"></hui-checkbox>

API

Attributes6
Attributes
NameTypeDefaultDescription
namestring''The form field name. With no name the control contributes no entry to FormData.
disabledbooleanfalseDisables the internal button and clears the form value.
checkedbooleanfalseThe checked state. Reflected, so it can be styled and read from the attribute.
indeterminatebooleanfalseDraws the mixed glyph and reports aria-checked="mixed". Cleared on the next toggle. Reflected.
valuestring'on'The value submitted while checked. Reflected.
requiredbooleanfalseReflected; marks the checkbox required for constraint validation.
Properties6
Properties
NameTypeDefaultDescription
namestring''Reflects to the name attribute.
disabledbooleanfalseReflects to the disabled attribute.
checkedbooleanfalseReflects to the checked attribute.
indeterminatebooleanfalseReflects to the indeterminate attribute.
valuestring'on'Reflects to the value attribute.
requiredbooleanfalseReflects to the required attribute.
Events3
Events
NameDescription
inputEmitted from the host after the checked flag flips. bubbles and composed; no detail.
changeEmitted from the host in the same turn as input. bubbles and composed; no detail.
clickThe internal button click is consumed with stopPropagation(), so a native click does not cross the shadow boundary. Bind to change instead.
CSS custom properties5
CSS custom properties
NameDefaultDescription
--hui-primaryoklch(0.496 0.265 301.924)Fill while checked or indeterminate.
--hui-backgroundoklch(1 0 0)Unchecked box fill.
--hui-inputoklch(0.62 0.019 323.02)Unchecked box border.
--hui-destructiveoklch(0.56 0.245 27.325)Border while aria-invalid="true".
--hui-focus-ring-width3pxWidth of the keyboard focus ring.
::part() hooks1
::part() hooks
NameDescription
controlThe internal native <button> that carries role="checkbox".

States

Checked and indeterminate

The two states a bare checkbox cannot both express: checked, and indeterminate for a parent whose children are partly selected, which is announced as mixed.

Checked and indeterminate
Source
<hui-checkbox name="checked" checked value="yes" aria-label="Checked"></hui-checkbox>
<hui-checkbox name="mixed" indeterminate aria-label="Mixed"></hui-checkbox>

Disabled

Disabled in both states. The control keeps its name for a screen reader but cannot be reached or changed.

Disabled
Source
<hui-checkbox name="off" disabled aria-label="Disabled"></hui-checkbox>
<hui-checkbox name="on" checked disabled aria-label="Checked and disabled"></hui-checkbox>

Server-side mechanics

The server owns name, value, checked, indeterminate, required and disabled. A checked box submits its value under name; an unchecked or unnamed box submits nothing, exactly like a native checkbox. A swap must re-send checked, and indeterminate if the mixed state is still wanted, because those attributes are the only state the server can restore, and swapping mid-toggle discards the flip. Validation comes from required, which blocks submission, and from aria-invalid="true" or a hui-field invalid wrapper for the border.

Accessibility

  • The internal button exposes role="checkbox" with aria-checked of true, false or mixed.
  • The accessible name comes from an aria-label; wrapping the host in a <label> does not name the shadow button.
  • Indeterminate is visual and announced; the next activation clears it and sets a definite checked state.
  • Because required and validity live on the host through ElementInternals, a required unchecked box blocks submission like the native control.

Keyboard

Keyboard
KeysAction
TabMoves focus to and from the checkbox; it is a single tab stop.
Space, EnterToggles the checked state. The internal native button supplies both keys.

Gotchas

  • The internal click is stopped at the shadow boundary, so a native click listener on the host never fires; bind to input or change instead.