Kern GitHub

Checkbox

Native checkbox with explicit label association, help text, and error messaging.

Examples

Default preview

Native checkbox only: no custom role. The inline SVG check is revealed by the checked peer state so it remains visible in forced-colors mode. Indeterminate is deliberately not part of the API (tenet 10); consumers who need it should copy the component and add the native el.indeterminate = true behavior themselves.

Default + help text

Monthly product notes and design-system updates.

Required before creating an account.

Error + disabled

Accept the privacy policy before continuing.

This setting cannot be changed by your role.

1<div class="space-y-8">
2 <p class="text-muted-foreground text-sm">
3 Native checkbox only: no custom role. The inline SVG check is revealed by the checked peer state so it remains
4 visible in forced-colors mode. Indeterminate is deliberately not part of the API (tenet 10); consumers who need it
5 should copy the component and add the native <code>el.indeterminate = true</code> behavior themselves.
6 </p>
7
8 <section class="space-y-4">
9 {{ partial:docs/components/label content="Default + help text" }}
10 <div class="grid gap-4 md:grid-cols-2">
11 {{ partial:components/forms/checkbox id="newsletter" name="newsletter" value="yes" label="Send me the editorial newsletter" }}
12 {{ slot:help }}Monthly product notes and design-system updates.{{ /slot:help }}
13 {{ /partial:components/forms/checkbox }}
14
15 {{ partial:components/forms/checkbox id="terms" name="terms" value="accepted" label="I agree to the terms" checked="true" }}
16 {{ slot:help }}Required before creating an account.{{ /slot:help }}
17 {{ /partial:components/forms/checkbox }}
18 </div>
19 </section>
20
21 <section class="space-y-4">
22 {{ partial:docs/components/label content="Error + disabled" }}
23 <div class="grid gap-4 md:grid-cols-2">
24 {{ partial:components/forms/checkbox id="privacy" name="privacy" value="accepted" label="I accept the privacy policy" error="true" }}
25 {{ slot:error }}Accept the privacy policy before continuing.{{ /slot:error }}
26 {{ /partial:components/forms/checkbox }}
27
28 {{ partial:components/forms/checkbox id="locked" name="locked" value="yes" label="Managed by organization policy" disabled="true" checked="true" }}
29 {{ slot:help }}This setting cannot be changed by your role.{{ /slot:help }}
30 {{ /partial:components/forms/checkbox }}
31 </div>
32 </section>
33</div>

Props

Name Type Default Description
id string Checkbox id used by the label and described-by wiring (falls back to name/value)
name string Name attribute used for form submissions
value string Value attribute used for form submissions
label string Option label text
checked boolean false Checked state
disabled boolean false Disabled state
error boolean false Enables destructive visual state and aria-invalid
class string Additional classes merged via tw_merge (root element only)

Source

1{{#
2 @name Checkbox
3 @desc Native checkbox with explicit label association, help text, and error messaging.
4 @param id string - Checkbox id used by the label and described-by wiring (falls back to name/value)
5 @param name string - Name attribute used for form submissions
6 @param value string - Value attribute used for form submissions
7 @param label string - Option label text
8 @param checked boolean [false] - Checked state
9 @param disabled boolean [false] - Disabled state
10 @param error boolean [false] - Enables destructive visual state and aria-invalid
11 @param class string - Additional classes merged via tw_merge (root element only)
12 @slot help - Help text rendered below the checkbox
13 @slot error - Error message rendered below the checkbox and referenced by aria-describedby
14#}}
15{{ _help_slot = slot:help }}
16{{ _error_slot = slot:error }}
17{{ _field_id = id ?? '' }}
18{{ if !_field_id }}
19 {{ if name }}
20 {{ _field_id = name }}
21 {{ if value }}
22 {{ _field_id = '{name}-{value}' }}
23 {{ /if }}
24 {{ else }}
25 {{ _field_id = 'checkbox' }}
26 {{ /if }}
27{{ /if }}
28{{ _describedby = '' }}
29{{ if _field_id }}
30 {{ if _error_slot }}
31 {{ _describedby = '{_field_id}-error' }}
32 {{ elseif _help_slot }}
33 {{ _describedby = '{_field_id}-help' }}
34 {{ /if }}
35{{ /if }}
36{{ _root_classes = 'space-y-1 {class}'
37 | tw_merge }}
38{{ _checkbox_classes = 'peer border-foreground checked:bg-foreground aria-invalid:border-destructive focus-visible:border-focus-text focus-visible:outline-focus disabled:border-muted-foreground disabled:bg-muted size-5 shrink-0 appearance-none border-2 bg-transparent focus-visible:outline focus-visible:outline-4 disabled:cursor-not-allowed'
39 | tw_merge }}
40{{ _label_classes = 'text-foreground text-sm'
41 | tw_merge }}
42{{ if disabled }}
43 {{ _label_classes = 'text-muted-foreground text-sm'
44 | tw_merge }}
45{{ /if }}
46<div class="{{ _root_classes }}">
47 <div class="flex items-start gap-3">
48 <span class="relative mt-0.5 flex size-5 shrink-0 items-center justify-center">
49 <input
50 class="{{ _checkbox_classes }}"
51 type="checkbox"
52 {{ if name }}name="{{ name }}"{{ /if }}
53 {{ if value }}value="{{ value }}"{{ /if }}
54 id="{{ _field_id }}"
55 {{ if checked }}checked{{ /if }}
56 {{ if disabled }}disabled{{ /if }}
57 {{ if error }}aria-invalid="true"{{ /if }}
58 {{ if _describedby }}aria-describedby="{{ _describedby }}"{{ /if }}
59 />
60 <span
61 class="text-background peer-disabled:text-muted-foreground pointer-events-none absolute inset-0 hidden items-center justify-center peer-checked:flex"
62 aria-hidden="true"
63 >
64 {{ svg src="icons/check" class="size-4 fill-current" }}
65 </span>
66 </span>
67 <label class="{{ _label_classes }}" for="{{ _field_id }}">
68 {{ label }}
69 </label>
70 </div>
71 {{ if _error_slot }}
72 <p class="text-destructive text-sm font-bold" id="{{ _field_id }}-error">
73 {{ _error_slot }}
74 </p>
75 {{ elseif _help_slot }}
76 <p class="text-muted-foreground text-sm" id="{{ _field_id }}-help">
77 {{ _help_slot }}
78 </p>
79 {{ /if }}
80</div>

Dependencies

Packages

marcorieser/tailwind-merge-statamic

1composer require marcorieser/tailwind-merge-statamic

Internal dependencies

  • Slots: help, error