Checkbox
Checkbox and radio controls for picking options, with a linked label and description.
import { Checkbox, Radio, RadioGroup } from '@aksornproject/aksara-ui'Label and description
label renders a real <label> linked to the control, so clicking the text toggles it. description renders under the label and is linked with aria-describedby. A long label wraps and the control stays on its first line.
<div className="flex flex-col gap-spacing-12">
<Checkbox
label="Email me about new lessons"
description="A weekly digest, every Monday."
defaultChecked
/>
<Checkbox label="Send reminders before class" />
</div>Indeterminate
indeterminate draws a dash for a parent whose children are partly selected. The library does not wrap Base UI CheckboxGroup, so you derive checked and indeterminate from your own state. onCheckedChange receives the next checked boolean first.
<div className="flex flex-col gap-spacing-12">
<Checkbox
label="All subjects"
checked={all}
indeterminate={some}
onCheckedChange={(checked) => setSelected(checked ? SUBJECTS : [])}
/>
<div className="flex flex-col gap-spacing-12 ps-spacing-32">
{SUBJECTS.map((subject) => (
<Checkbox
key={subject}
label={subject}
checked={selected.includes(subject)}
onCheckedChange={(checked) => toggle(subject, checked)}
/>
))}
</div>
</div>Sizes
medium is a 20px control and the default. large is 24px. The label and description are 16px at both sizes.
<Checkbox label="Medium" defaultChecked />
<Checkbox size="large" label="Large" defaultChecked />States
disabled greys the control and its text and sets a not-allowed cursor. readOnly keeps the default look without hover and blocks changes. loading turns the control, label and description into skeleton blocks, sets aria-busy and blocks changes.
<div className="flex flex-col gap-spacing-12">
<Checkbox label="Disabled" disabled />
<Checkbox label="Disabled and checked" disabled defaultChecked />
<Checkbox label="Read-only" readOnly defaultChecked />
<Checkbox label="Loading" description="Fetching your settings" loading />
</div>Required
required marks the hidden input required and draws a red star after the label. Without a label there is no star. A Checkbox submits with its form through a hidden native input, which carries name, value and required.
<Checkbox
required
name="terms"
label="I accept the terms of use"
description="You can read them on the Help page."
/>Without a label
Without label or description the Checkbox renders only the control and its hidden input. Name it with aria-label, or point an external <label htmlFor> at its id. className lands on the control in both cases.
<Checkbox aria-label="Select row" />
<span className="flex items-center gap-spacing-8">
<Checkbox id="select-all-students" />
<label htmlFor="select-all-students">Select all students</label>
</span>Radio
mode="radio" renders a radio with the same sizes, states, label and description. A radio needs a value and a surrounding RadioGroup, which owns the value. TypeScript rejects checked, defaultChecked, onCheckedChange and indeterminate on a radio. RadioGroup adds no layout, so pass the classes you need. A disabled or read-only RadioGroup styles its items.
<RadioGroup
defaultValue="monthly"
aria-label="Billing"
className="flex flex-col gap-spacing-12"
>
<Checkbox mode="radio" value="monthly" label="Monthly" />
<Checkbox
mode="radio"
value="yearly"
label="Yearly"
description="Two months free"
/>
<Checkbox
mode="radio"
value="school"
label="School licence"
description="Contact sales"
disabled
/>
</RadioGroup>Radio namespace
Radio groups the radio parts under one name. Radio.Group is RadioGroup, and Radio.Item is a Checkbox with mode="radio". The two forms render the same thing, so pick one and use it across the app.
<Radio.Group
defaultValue="th"
aria-label="Language"
className="flex flex-col gap-spacing-12"
>
<Radio.Item value="th" label="ภาษาไทย" />
<Radio.Item value="en" label="English" />
</Radio.Group>Accessibility
- Give every control a name with
label, an external<label htmlFor>oraria-label. - An indeterminate checkbox announces
aria-checked="mixed". - The required star is
aria-hidden. The control announcesaria-required. loadingsetsaria-busyand blocks changes.- Arrow keys move the selection inside a
RadioGroup. - A decorative control inside a clickable card can take
tabIndex={-1},aria-hiddenandpointer-events-none. The card then owns the role and the keyboard.
API
Checkbox
Prop
Type
RadioGroup
Radio.Group takes the same props.
Prop
Type
Radio.Item
Prop
Type