J3W1 / DESIGN SYSTEM
Checkbox
The native checkbox drawn as a 16px square that fills with the primary action colour and a ✓ or – glyph; single, or a fieldset group of independent choices.
stable · LIGHT DOM · 1.1.0
Visible native controls retain FormData, labels, constraints, disabled fieldsets and reset. No duplicate form-value mechanism is installed.
Live variants
default
<j3w1-checkbox id="example-checkbox-default"><div class="checkbox">
<label class="checkbox-option">
<span class="checkbox-control">
<input class="checkbox-input" type="checkbox" name="example-checkbox-default-wrap" aria-describedby="example-checkbox-default-cb-wrap-message">
<svg class="checkbox-check" aria-hidden="true" focusable="false" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square"><path d="M3.5 8.5l3 3 6-6"></path></svg>
<svg class="checkbox-dash" aria-hidden="true" focusable="false" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square"><path d="M4 8h8"></path></svg>
</span>
<span class="checkbox-text">Wrap long lines <span class="checkbox-required" aria-hidden="true">*</span><span class="checkbox-required sr-only"> required</span></span>
</label>
<p class="checkbox-message" id="example-checkbox-default-cb-wrap-message">✕ Confirm before continuing.</p>
</div></j3w1-checkbox>group
<j3w1-checkbox id="example-checkbox-group"><fieldset class="checkbox checkbox-group" aria-describedby="example-checkbox-group-cb-modules-message">
<legend class="checkbox-legend">Bar modules <span class="checkbox-required" aria-hidden="true">*</span><span class="checkbox-required sr-only"> required</span></legend>
<label class="checkbox-option">
<span class="checkbox-control">
<input class="checkbox-input" type="checkbox" name="example-checkbox-group-modules" value="cpu">
<svg class="checkbox-check" aria-hidden="true" focusable="false" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square"><path d="M3.5 8.5l3 3 6-6"></path></svg>
<svg class="checkbox-dash" aria-hidden="true" focusable="false" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square"><path d="M4 8h8"></path></svg>
</span>
<span class="checkbox-text">CPU load</span>
</label>
<label class="checkbox-option">
<span class="checkbox-control">
<input class="checkbox-input" type="checkbox" name="example-checkbox-group-modules" value="memory">
<svg class="checkbox-check" aria-hidden="true" focusable="false" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square"><path d="M3.5 8.5l3 3 6-6"></path></svg>
<svg class="checkbox-dash" aria-hidden="true" focusable="false" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square"><path d="M4 8h8"></path></svg>
</span>
<span class="checkbox-text">Memory</span>
</label>
<label class="checkbox-option">
<span class="checkbox-control">
<input class="checkbox-input" type="checkbox" name="example-checkbox-group-modules" value="battery">
<svg class="checkbox-check" aria-hidden="true" focusable="false" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square"><path d="M3.5 8.5l3 3 6-6"></path></svg>
<svg class="checkbox-dash" aria-hidden="true" focusable="false" width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="square"><path d="M4 8h8"></path></svg>
</span>
<span class="checkbox-text">Battery</span>
</label>
<p class="checkbox-message" id="example-checkbox-group-cb-modules-message">✕ Choose at least one module.</p>
</fieldset></j3w1-checkbox>Install and register
Use the exact version. If npm publication is pending, install the release tarball from the installation guide.
npm install --save-exact @j3w1/ui@1.1.0import '@j3w1/ui/tokens.css';
import '@j3w1/ui/styles/checkbox.css';
import '@j3w1/ui/register/checkbox';Insert the maintained markup above after loading these imports. Its native children provide accessible names and form behavior; the empty custom tag alone does not create a control.
Copy the complete implementation
npx --package=@j3w1/ui@1.1.0 j3w1-ui copy checkbox --out ./vendor/j3w1/checkboxThe CLI verifies every file before writing and refuses overwrites. Serve the output over HTTP and open index.html. Keep its modules, CSS, tokens and licence notices together.
Public API
attributes
| Name | Type / signature | Meaning |
|---|---|---|
disabled | CustomEvent | Disable the native controls owned by this instance. |
loading | CustomEvent | Mark the primary control busy and prevent duplicate activation. |
value | CustomEvent | Forwards value to the primary native control. |
required | CustomEvent | Forwards required to the primary native control. |
readonly | CustomEvent | Forwards readonly to the primary native control. |
checked | CustomEvent | Forwards checked to the primary native control. |
properties
| Name | Type / signature | Meaning |
|---|---|---|
disabled | boolean | Delegates disabled state to native children. |
name | string | Native control name; application form keys remain explicit. |
value | string | Primary native value; assignment does not fabricate user events. |
checked | boolean | Native checkbox state. |
required | boolean | Native required constraint. |
readOnly | boolean | Native readonly property. |
form | HTMLFormElement | null | Owning native form. Read only. |
indeterminate | boolean | Native mixed state; Space changes a mixed checkbox to checked. |
values | string[] | Values of checked native options in this instance. |
methods
| Name | Type / signature | Meaning |
|---|---|---|
refresh | (): void | Reconnect behavior after replacing native child structure. |
focus | (options?: FocusOptions): void | Focus the first usable native control. |
checkValidity | (): boolean | Check owned native constraints. |
reportValidity | (): boolean | Report the first invalid owned control. |
clear | (): void | Clear an editable primary input and emit native input/change. |
events
| Name | Type / signature | Meaning |
|---|---|---|
j3w1-change | CustomEvent | Native change from an owned control, alongside the original native event. |
Dependencies and verification
Registered components: none. Style dependencies: none.
Package presence establishes an available implementation. Actual passes depend on the tested artifact and environment. Read specification execution evidence; read packed-consumer evidence; inspect the complete state matrix.
Full implementation manifest, API and token dependency closure
Canonical specification
Purpose
An independent yes/no choice, or several of them under one legend. A setting that takes effect immediately is a switch; one of several exclusive options is a radio group. A parent checkbox over a partly selected set shows the mixed state.
Anatomy
The box is the native input itself with appearance: none, so it keeps
native focus, form and keyboard behaviour. The ✓ and – glyphs are inline
SVGs stacked over it in the same 16px cell. The option row is a <label>,
at least 24px tall, which makes the text part of the target. A group is a
<fieldset> with a <legend>.
States
| State | Visual | Non-colour channel |
|---|---|---|
| default | 16px box, 1px color.border.control on color.surface.input; text color.text.default | — |
| hover | box background → color.interaction.hover.bg; checked box → color.action.primary.hover-bg | cursor: pointer; hover-capable pointers only |
| focus-visible | ring 1px dashed color.interaction.focus.ring at −2px around the box | the ring |
| checked | box fills color.action.primary.bg; ✓ in color.action.primary.text; border stays color.border.control | the ✓ glyph; checked |
| mixed | box fills color.action.primary.bg; – in color.action.primary.text | the – glyph; indeterminate / aria-checked="mixed" |
| checked+focus-visible | the fill and a ring in color.interaction.focus.ring-container | glyph and ring |
| checked+disabled | box color.interaction.disabled.bg with 1px color.border.disabled; ✓ and text in color.text.disabled | glyph; disabled; cursor: not-allowed |
| disabled | box color.interaction.disabled.bg with 1px color.border.disabled; text color.text.disabled | disabled; cursor: not-allowed |
| invalid | box border 2px color.status.danger.border; message with the ✕ glyph | border width 1 → 2px; glyph; aria-invalid |
| required | * after the text or legend in color.status.danger.text plus visually hidden “required” | required; the mark |
Precedence: disabled > invalid > checked > hover; focus-visible is always drawn.
Keyboard
Native. Space toggles; Enter does nothing. Every checkbox in a group is a separate tab stop, unlike radios. A mixed parent becomes checked on the first Space and unchecked on the second, never mixed again by keyboard.
Accessibility
The text is the label through the wrapping <label>; a group has its
legend read before each option. indeterminate is a DOM property with no
attribute, so the host mirrors it to data-state-mixed for styling and the
state reads as “mixed” natively. A required group marks the legend, not
every option, and validates on submit. Contrast: text 8.43:1, glyph 9.28:1
on the fill, box edge 4.45:1 on the input surface and 4.33:1 against the
panel when checked, ring 4.69:1, container ring 5.57:1 on the fill.
Portability
A square with a border and a fill plus two glyphs. Hosts that draw their own indicator set it square, 16px, and use the same fill and glyph colours; a host without a mixed indicator draws the dash itself or records the gap.
Non-examples
Rounded or circular boxes. A tick drawn with a border trick or an icon
font. A checked state shown by border colour alone with no glyph. A box
smaller than 16px or a row shorter than 24px. The mixed state used as a
third value. A checkbox that saves on change. Disabling by opacity. A div
with role="checkbox".