Installation
Install the dependencies
pnpm add cn class-variance-authority github:sveltery/baseCopy the component
Copy the following files into src/lib/components/ui/checkbox.
<script lang="ts">
import type { ComponentProps } from 'svelte';
import { Checkbox as Primitive } from '@sveltery/base/checkbox';
import { cn } from 'cn';
import CheckIcon from '@lucide/svelte/icons/check';
let { checked = $bindable(), class: classProp, ...props }: Omit<ComponentProps<typeof Primitive.Root>, 'children'> = $props();
</script>
<Primitive.Root data-slot="checkbox" bind:checked {...props} class={cn('border-input dark:bg-input/30 data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary data-checked:border-primary aria-invalid:aria-checked:border-primary aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 flex size-4 items-center justify-center rounded-[4px] border transition-colors group-has-disabled/field:opacity-50 focus-visible:ring-3 aria-invalid:ring-3 group-has-[:focus-visible]/field-label:ring-0 group-has-[:focus-visible]/field-label:not-data-checked:border-input group-has-[:focus-visible]/field-label:data-checked:border-primary peer relative shrink-0 outline-none after:absolute after:-inset-x-3 after:-inset-y-2 disabled:cursor-not-allowed disabled:opacity-50', classProp)}>
<Primitive.Indicator data-slot="checkbox-indicator" class="[&>svg]:size-3.5 grid place-content-center text-current transition-none">
<CheckIcon />
</Primitive.Indicator>
</Primitive.Root>export { default as Checkbox } from './Checkbox.svelte';Update the import paths
Change the imports to match your project setup.
Usage
<script lang="ts">
import { Checkbox } from '$lib/components/ui/checkbox';
import { Label } from '$lib/components/ui/label';
</script><Checkbox id="terms" />
<Label for="terms">Accept terms and conditions</Label>Checked state
Checkbox works like an HTML checkbox. Use defaultChecked for the initial state, or bind:checked to read and set it.
<script lang="ts">
let checked = $state(false);
</script>
<Checkbox bind:checked />Forms
A checkbox with a name submits with its form, as on or its value when checked. An unchecked or disabled checkbox submits nothing.
<form method="POST">
<Checkbox name="terms" value="accepted" defaultChecked />
<button type="submit">Save</button>
</form>Invalid state
Set aria-invalid on the checkbox to show the invalid styles.
<Checkbox id="terms" aria-invalid="true" />Disabled
Set disabled to prevent interaction.
<Checkbox id="toggle" disabled />API reference
Checkbox is styled on top of the Sveltery Base Checkbox primitive, which owns its behavior, form submission and accessibility. See the Base UI Checkbox documentation for the behavior it ports.