Kern GitHub

Select

Native select form control using the OS picker; a custom listbox keyboard/ARIA contract cannot be met more robustly, so Kern deliberately does not ship one.

Examples

Default preview

Default + help text

Used for scheduled publishing and notifications.

Error + disabled

Choose a plan before continuing.

Roles are managed by your organization admin.

1<div class="space-y-8">
2 <section class="space-y-4">
3 {{ partial:docs/components/label content="Default + help text" }}
4 <div class="grid gap-4 md:grid-cols-2">
5 {{ partial:components/forms/select name="country" }}
6 {{ slot:label }}Country{{ /slot:label }}
7 <option value="">Choose a country</option>
8 <option value="ch">Switzerland</option>
9 <option value="de">Germany</option>
10 <option value="fr">France</option>
11 {{ /partial:components/forms/select }}
12
13 {{ partial:components/forms/select name="timezone" }}
14 {{ slot:label }}Timezone{{ /slot:label }}
15 {{ slot:help }}Used for scheduled publishing and notifications.{{ /slot:help }}
16 <option value="Europe/Zurich">Europe/Zurich</option>
17 <option value="Europe/Berlin">Europe/Berlin</option>
18 <option value="Europe/Paris">Europe/Paris</option>
19 {{ /partial:components/forms/select }}
20 </div>
21 </section>
22
23 <section class="space-y-4">
24 {{ partial:docs/components/label content="Error + disabled" }}
25 <div class="grid gap-4 md:grid-cols-2">
26 {{ partial:components/forms/select name="plan" error="true" }}
27 {{ slot:label }}Plan{{ /slot:label }}
28 {{ slot:error }}Choose a plan before continuing.{{ /slot:error }}
29 <option value="">Choose a plan</option>
30 <option value="starter">Starter</option>
31 <option value="team">Team</option>
32 <option value="enterprise">Enterprise</option>
33 {{ /partial:components/forms/select }}
34
35 {{ partial:components/forms/select name="role" disabled="true" }}
36 {{ slot:label }}Role{{ /slot:label }}
37 {{ slot:help }}Roles are managed by your organization admin.{{ /slot:help }}
38 <option value="owner">Owner</option>
39 <option value="editor">Editor</option>
40 <option value="viewer">Viewer</option>
41 {{ /partial:components/forms/select }}
42 </div>
43 </section>
44</div>

Props

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

Source

1{{#
2 @name Select
3 @desc Native select form control using the OS picker; a custom listbox keyboard/ARIA contract cannot be met more robustly, so Kern deliberately does not ship one.
4 @param id string - Select id used by the label and described-by wiring (falls back to name)
5 @param name string - Name attribute used for form submissions
6 @param error boolean [false] - Enables destructive visual state and aria-invalid
7 @param disabled boolean [false] - Disabled state
8 @param class string - Additional classes merged via tw_merge (root element only)
9 @slot default - Option elements rendered inside the native select
10 @slot label - Field label content
11 @slot help - Help text rendered below the control
12 @slot error - Error message rendered below the control and referenced by aria-describedby
13#}}
14{{ _label_slot = slot:label }}
15{{ _help_slot = slot:help }}
16{{ _error_slot = slot:error }}
17{{ _field_id = id ?? name ?? '' }}
18{{ _describedby = '' }}
19{{ if _field_id }}
20 {{ if _error_slot }}
21 {{ _describedby = '{_field_id}-error' }}
22 {{ elseif _help_slot }}
23 {{ _describedby = '{_field_id}-help' }}
24 {{ /if }}
25{{ /if }}
26{{ _select_classes = 'text-foreground disabled:text-muted-foreground h-10 w-full appearance-none bg-transparent px-3 pr-10 text-sm focus:outline-none disabled:cursor-not-allowed'
27 | tw_merge }}
28{{ partial:components/forms/field-wrapper for="{_field_id}" error="{error}" disabled="{disabled}" class="{class}" }}
29 {{ if _label_slot }}
30 {{ slot:label }}
31 {{ _label_slot }}
32 {{ /slot:label }}
33 {{ /if }}
34 {{ if _help_slot }}
35 {{ slot:help }}
36 {{ _help_slot }}
37 {{ /slot:help }}
38 {{ /if }}
39 {{ if _error_slot }}
40 {{ slot:error }}
41 {{ _error_slot }}
42 {{ /slot:error }}
43 {{ /if }}
44 <div class="relative">
45 <select
46 class="{{ _select_classes }}"
47 {{ if name }}name="{{ name }}"{{ /if }}
48 {{ if _field_id }}id="{{ _field_id }}"{{ /if }}
49 {{ if disabled }}disabled{{ /if }}
50 {{ if error }}aria-invalid="true"{{ /if }}
51 {{ if _describedby }}aria-describedby="{{ _describedby }}"{{ /if }}
52 >
53 {{ slot }}
54 </select>
55 <span
56 class="text-muted-foreground pointer-events-none absolute top-1/2 right-3 -translate-y-1/2"
57 aria-hidden="true"
58 >
59 {{ svg src="icons/chevron-down" class="size-4" }}
60 </span>
61 </div>
62{{ /partial:components/forms/field-wrapper }}

Dependencies

Packages

marcorieser/tailwind-merge-statamic

1composer require marcorieser/tailwind-merge-statamic

Internal dependencies

  • components/forms/_field-wrapper (internal partial — copy it alongside this component)
  • Slots: label, help, error, default option elements