Overview
The Checkbox component provides an accessible and customizable checkbox input with built-in support for checked, unchecked, and indeterminate states. It features smooth animations and custom content rendering.
Installation
npm install @svelte-atoms/core
Basic Usage
<script>
import { Checkbox } from '@svelte-atoms/core/components/checkbox';
let checked = $state(false);
</script>
<Checkbox bind:checked />
Examples
Basic Checkbox
<script>
let checked = $state(false);
</script>
<Checkbox bind:checked />
<p>Checked: {checked}</p>
Checkbox with Label
<script>
import { Checkbox } from '@svelte-atoms/core/components/checkbox';
import { Label } from '@svelte-atoms/core/components/label';
let agreed = $state(false);
</script>
<div class="flex items-center gap-2">
<Checkbox id="terms" bind:checked={agreed} />
<Label for="terms">I agree to the terms and conditions</Label>
</div>
Indeterminate State
<script>
let indeterminate = $state(true);
</script>
<Checkbox bind:indeterminate />
Checkbox Group
<script>
let group = $state([]);
</script>
<div class="flex flex-col gap-2">
<Checkbox value="option1" bind:group>Option 1</Checkbox>
<Checkbox value="option2" bind:group>Option 2</Checkbox>
<Checkbox value="option3" bind:group>Option 3</Checkbox>
</div>
<p>Selected: {group.join(', ')}</p>
Custom Checkmark
<script>
import { Checkbox } from '@svelte-atoms/core/components/checkbox';
import CustomIcon from './CustomIcon.svelte';
let checked = $state(false);
</script>
<Checkbox bind:checked checkedContent={CustomIcon} />
Disabled State
<Checkbox checked disabled>Disabled Checked</Checkbox>
<Checkbox disabled>Disabled Unchecked</Checkbox>
Handling State Cycle
<script>
let checked = $state(false);
let indeterminate = $state(true);
</script>
<!-- Click cycle: indeterminate → checked → unchecked → checked → ... -->
<Checkbox bind:checked bind:indeterminate />
Props
The checked state of the checkbox. Bindable for two-way data binding.
The indeterminate state. When true, shows indeterminate indicator. Bindable.
The value associated with this checkbox, used when working with checkbox groups.
Array of selected values for checkbox groups. Bindable.
When true, the checkbox is disabled and cannot be interacted with.
The ID attribute, used for associating with labels.
The name attribute for form submission.
Custom content to display when the checkbox is checked.
Custom content to display when the checkbox is in indeterminate state.
preset
string
default:"'checkbox'"
The preset key used for styling.
Additional CSS classes to apply to the checkbox element.
Custom enter transition function.
Custom exit transition function.
Whether to apply the initial transition.
Event Handlers
Click event handler. Called before state changes. Can prevent default behavior.
onchange
(ev?: Event, options?: { checked: boolean }) => void
Change event handler. Called after the checkbox state changes.
oninput
(ev?: Event, options?: { checked: boolean, value: boolean, type: 'boolean' }) => void
Input event handler. Called when the checkbox value changes.
HTML Attributes
The Checkbox component accepts all standard HTML input attributes (excluding type), including:
tabindex - Tab order
aria-* - Accessibility attributes
data-* - Data attributes
Default Styling
/* Root */
border-border
outline-primary
bg-input
text-foreground
aspect-square
h-5
w-fit
cursor-pointer
rounded-sm
border
outline-0
outline-offset-2
transition-colors
duration-100
/* When checked */
bg-foreground
/* Checkmark indicator */
text-accent
pointer-events-none
flex
h-full
content-center
items-center
justify-center
overflow-hidden
p-0.5
/* Indeterminate indicator */
pointer-events-none
flex
size-full
scale-50
items-center
justify-center
rounded-[inherit]
bg-current
State Behavior
The checkbox follows this state cycle when clicked:
- Indeterminate → Click → Checked (indeterminate becomes false, checked becomes true)
- Checked → Click → Unchecked (checked toggles to false)
- Unchecked → Click → Checked (checked toggles to true)
TypeScript Support
interface CheckboxProps extends HtmlAtomProps<'button'>, CheckboxExtendProps {
value?: string;
group?: string[];
checked?: boolean;
indeterminate?: boolean;
checkedContent?: Component | Snippet;
indeterminateContent?: Component | Snippet;
children?: Snippet<[]>;
onclick?: (ev?: Event) => void;
onchange?: (ev?: Event, options?: { checked: boolean }) => void;
}
Extending Checkbox Props
declare module '@svelte-atoms/core/components/checkbox' {
interface CheckboxExtendProps {
size?: 'sm' | 'md' | 'lg';
variant?: 'default' | 'rounded';
}
}
Animations
The checkbox includes built-in scale animation for the checkmark:
// Default animation
scale(node, {
duration: DURATION.fast,
easing: circOut,
start: 0.6
})
You can customize animations using enter and exit props:
<script>
import { fade } from 'svelte/transition';
</script>
<Checkbox
bind:checked
enter={(node) => fade(node, { duration: 200 })}
exit={(node) => fade(node, { duration: 200 })}
/>
Integration with Forms
<script>
import { Form } from '@svelte-atoms/core/components/form';
import { Checkbox } from '@svelte-atoms/core/components/checkbox';
import { z } from 'zod';
const schema = z.object({
isAdmin: z.boolean()
});
</script>
<Form.Root>
<Form.Field name="isAdmin" schema={schema.shape.isAdmin}>
<Form.Field.Label>Is Admin?</Form.Field.Label>
<Form.Field.Control base={Checkbox} />
</Form.Field>
</Form.Root>
Accessibility
- Uses proper ARIA role:
role="checkbox"
- Supports
aria-checked with three states: true, false, "mixed" (indeterminate)
- Keyboard accessible (Space/Enter to toggle)
- Hidden native checkbox for form compatibility
- Supports focus management
- Works with labels via
id attribute
Presets
The Checkbox component supports multiple preset keys:
checkbox - Root element
checkbox.checkmark - Checkmark indicator
checkbox.indeterminate - Indeterminate indicator
<Checkbox preset="checkbox.large" />
Best Practices
- Always provide labels: Use the Label component or text adjacent to checkboxes
- Use indeterminate for parent selections: In tree structures, show indeterminate when some children are selected
- Handle disabled state: Provide visual feedback for disabled checkboxes
- Group related checkboxes: Use the
group binding for related options
- Validate selections: Use with Form.Field for validation support
- Don’t use for single yes/no: Consider using a toggle or switch component instead
Common Patterns
Select All with Indeterminate
<script>
let items = $state(['item1', 'item2', 'item3']);
let selected = $state([]);
const allChecked = $derived(selected.length === items.length);
const someChecked = $derived(selected.length > 0 && selected.length < items.length);
function toggleAll() {
if (allChecked) {
selected = [];
} else {
selected = [...items];
}
}
</script>
<Checkbox
checked={allChecked}
indeterminate={someChecked}
onclick={toggleAll}
>
Select All
</Checkbox>
{#each items as item}
<Checkbox value={item} bind:group={selected}>{item}</Checkbox>
{/each}
Related Components
- Radio - For mutually exclusive selections
- Form - For form management
- Label - For checkbox labels