Skip to main content

Checkbox

<zeno-checkbox>FormsForm controlSource

A checkbox. It takes part in forms as a native checkbox does and has an indeterminate state.

import '@usezeno/tokens/css';
import '@usezeno/core/web-components';

Examples​

Basic​

The text comes from label. indeterminate shows a dash for a group that is partly selected. It is cleared when the user makes a choice.

<zeno-checkbox label="Send me a weekly summary"></zeno-checkbox>
<zeno-checkbox label="Remember this device" checked></zeno-checkbox>
<zeno-checkbox label="Select all files" indeterminate></zeno-checkbox>

Sizes​

<zeno-checkbox size="sm" label="Small"></zeno-checkbox>
<zeno-checkbox size="md" label="Medium"></zeno-checkbox>
<zeno-checkbox size="lg" label="Large"></zeno-checkbox>

Disabled, loading and error​

loading shows a spinner in the box and stops changes. error marks the checkbox as invalid and shows the text under it.

<zeno-checkbox label="Disabled" disabled></zeno-checkbox>
<zeno-checkbox label="Disabled and checked" disabled checked></zeno-checkbox>
<zeno-checkbox label="Saving your choice" loading></zeno-checkbox>
<zeno-checkbox label="I accept the terms" error="Accept the terms to continue."></zeno-checkbox>

Events​

A change by the user fires input and then change. Both carry checked, value and indeterminate in event.detail.

Not changed yet.

<zeno-checkbox label="Share usage data" value="usage"></zeno-checkbox>
<p data-result>Not changed yet.</p>
document.querySelector('zeno-checkbox').addEventListener('change', event => {
document.querySelector('[data-result]').textContent =
'checked: ' + event.detail.checked + ', value: ' + event.detail.value;
});

In a form​

A checked box sends its name with its value, or with “on” when no value is set. An unchecked box sends nothing. A required box must be checked before the form submits.

Create account Reset

Nothing submitted yet.

<form>
<zeno-checkbox name="terms" label="I accept the terms" required></zeno-checkbox>
<zeno-checkbox name="updates" value="weekly" label="Send me a weekly summary" checked></zeno-checkbox>
<zeno-button type="submit">Create account</zeno-button>
<zeno-button type="reset" variant="ghost">Reset</zeno-button>
<p data-result>Nothing submitted yet.</p>
</form>
const form = document.querySelector('form');
form.addEventListener('submit', event => {
event.preventDefault();
const sent = [...new FormData(form)].map(([name, value]) => name + '=' + value);
document.querySelector('[data-result]').textContent = 'Submitted: ' + sent.join('&');
});

Attributes and properties​

PropertyAttributeTypeDefaultDescription
checkedcheckedreflectsbooleanfalse
indeterminateindeterminatereflectsbooleanfalse
sizesizereflects'sm' | 'md' | 'lg''md'
loadingloadingreflectsbooleanfalse
defaultCheckedbooleanfalseWhether it is checked when its form is reset.
valuevalueFormValue'on' From FormFieldMixin.
namenamereflectsstring From FormFieldMixin.
requiredrequiredreflectsbooleanfalse From FormFieldMixin.
disableddisabledreflectsbooleanfalse From FormFieldMixin.
readonlyreadonlyreflectsbooleanfalse From FormFieldMixin.
errorerrorstringAn error to show, for example one a server returned. From FormFieldMixin.
labellabelstringA visible label. An outside <label for> works as well. From FormFieldMixin.
hideRequiredIndicatorhide-required-indicatorbooleanfalse From FormFieldMixin.
touchedbooleanfalseTrue once the user has left the control or a submit was refused. From FormFieldMixin.
dirtybooleanfalseTrue once the user has changed the value. From FormFieldMixin.
defaultValueFormValue''The value the control goes back to when its form is reset. From FormFieldMixin.
formread onlyHTMLFormElement | null From FormFieldMixin.
labelsread onlyNodeList From FormFieldMixin.
validityread onlyValidityState From FormFieldMixin.
validationMessageread onlystring From FormFieldMixin.
willValidateread onlyboolean From FormFieldMixin.
isDisabledread onlybooleanTrue when the element or an ancestor fieldset disables it. From FormFieldMixin.
invalidread onlybooleanTrue when the control should look invalid. From FormFieldMixin.
testIdstringTest ID for automated testing From ZenoElement.

Methods​

MethodDescription
focus(options?: FocusOptions): voidFocus the component or its first focusable element From ZenoElement.
blur(): voidBlur the component or its focused element From ZenoElement.
checkValidity(): booleanReports whether the value is valid without showing anything. Use reportValidity() or validate() to show the result as well. From FormFieldMixin.
reportValidity(): boolean From FormFieldMixin.
setCustomValidity(message: string): void From FormFieldMixin.
validate(): booleanChecks validity and shows the result on the control. From FormFieldMixin.

Events​

EventDetailDescription
input{ checked: boolean; value: FormValue; indeterminate: boolean }The user checked or unchecked the box.
change{ checked: boolean; value: FormValue; indeterminate: boolean }The user checked or unchecked the box.

Slots​

This element has no slots.

CSS parts​

Part
base
box
error
icon
label
loading
required

CSS custom properties​

This element documents no custom properties of its own. Style it through its parts and through the tokens it reads.

The element's own source reads no tokens.

Types​

type FormValue = string | number | boolean | Date | null | undefined;

Accessibility​

Keyboard​

KeyWhat it does
TabMoves focus to the checkbox.
SpaceChecks or unchecks it.

Forms​

  • With a name, the element adds its value to the data of the form it is in, and is left out while it is disabled.
  • It is labelled by its label attribute or by a <label for> that points at its id.
  • It takes part in validation: checkValidity(), reportValidity() and setCustomValidity() work, and an invalid element blocks the submit and matches :invalid.
  • It follows a <fieldset disabled> around it and goes back to its first value when the form is reset.
  • The messages it writes itself, such as “Please fill out this field.”, are in English only.

Notes​

  • Renders a native <input type="checkbox"> in its shadow root, hidden visually but still the control that takes focus and keys. The role, the checked state and the mixed state of indeterminate are the browser’s own.
  • The native input sits inside a <label> with the label text, so the text names it and a click on the text toggles it.
  • A <label for> outside the element also works: its text becomes the aria-label of the input and a click on it toggles the checkbox. An aria-label on the element wins over it.
  • The input always has aria-invalid, "true" or "false". While the error text shows, aria-describedby points at it.
  • required is set on the native input. The asterisk after the label is hidden from assistive technology. When a required box is left unchecked, the error text is the browser’s own message for a checkbox, unless error is set.

Tests and known gaps​

  • Tested in a real browser by checkbox.test.ts.
  • Checked with axe-core in the light and the dark theme.
  • Has a Storybook story.
24 of the 39 properties, methods, events, slots and parts above have no description in the source
  • the property checked
  • the property indeterminate
  • the property size
  • the property loading
  • the property value
  • the property name
  • the property required
  • the property disabled
  • the property readonly
  • the property hideRequiredIndicator
  • the property form
  • the property labels
  • the property validity
  • the property validationMessage
  • the property willValidate
  • the method reportValidity()
  • the method setCustomValidity()
  • the part base
  • the part box
  • the part error
  • the part icon
  • the part label
  • the part loading
  • the part required

Known gaps:

  • The label is text only. There is no slot, so the label cannot hold a link, for example to the terms the user accepts.
  • readonly is accepted but does nothing. The checkbox can still be changed.
  • A loading checkbox is a disabled native input. It leaves the tab order, and assistive technology announces it as unavailable, the same as disabled.
  • The error text is not a live region. A screen reader reads it when focus is on the checkbox, but does not announce it when it appears.