Checkbox

A control that allows the user to toggle between checked and not checked.

Basic
With Description

By clicking this checkbox, you agree to the terms and conditions.

Invalid
Disabled
With Title
In Table
Name Email Role
Sarah Chen sarah.chen@example.com Admin
Marcus Rodriguez marcus.rodriguez@example.com User
Priya Patel priya.patel@example.com User
David Kim david.kim@example.com Editor
Group

Installation

Install the dependencies

pnpm add cn class-variance-authority github:sveltery/base

Copy the component

Copy the following files into src/lib/components/ui/checkbox.

src/lib/components/ui/checkbox/Checkbox.svelte
<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>
src/lib/components/ui/checkbox/index.ts
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.