Checkbox
A control that lets the user toggle between checked, unchecked, and indeterminate states.
Examples
Default checked
Use defaultChecked to set the initial state without controlling the component.
Disabled
Use the disabled prop to prevent interaction.
Controlled
Manage the checked state with React state using checked and onCheckedChange.
Group
Use CheckboxGroup to manage multiple related checkboxes. Each child checkbox uses a value prop that matches the group's value array.
Controlled group
Manage the group's selected values with React state using value and onValueChange.
Parent checkbox
Use a parent checkbox with the parent prop to control a group of child checkboxes. Pass allValues to CheckboxGroup so the parent can toggle all children. The parent automatically shows an indeterminate state when some children are selected.
Installation
Copy the source code below into your project:
import { Checkbox as BaseCheckbox } from "@base-ui/react/checkbox";
import { CheckboxGroup as BaseCheckboxGroup } from "@base-ui/react/checkbox-group";
import { cn } from "@/lib/utils";
import { AnimatePresence, motion } from "motion/react";
function CheckboxGroup({ className, ...props }: BaseCheckboxGroup.Props) {
return (
<BaseCheckboxGroup
className={cn("flex flex-col gap-2", className)}
data-slot="checkbox-group"
{...props}
/>
);
}
function Checkbox({ className, ...props }: BaseCheckbox.Root.Props) {
return (
<BaseCheckbox.Root
className={cn(
"data-disabled:pointer-not-allowed relative inline-flex size-4.5 shrink-0 items-center justify-center rounded-sm border border-input bg-muted ring-ring outline-none before:pointer-events-none hover:bg-muted-hover focus-visible:ring-2 focus-visible:ring-offset-1 focus-visible:ring-offset-background aria-invalid:border-destructive/36 focus-visible:aria-invalid:border-destructive/64 focus-visible:aria-invalid:ring-destructive/48 data-disabled:opacity-50 sm:size-4 dark:not-data-checked:bg-gray-950/32 dark:aria-invalid:ring-destructive/24",
"data-checked:bg-accent data-indeterminate:bg-accent",
className,
)}
data-slot="checkbox"
{...props}
>
<BaseCheckbox.Indicator
className="absolute inset-0 flex items-center justify-center rounded-sm"
data-slot="checkbox-indicator"
keepMounted
render={(props, state) => (
<span {...props}>
<AnimatePresence initial={false}>
{(state.checked || state.indeterminate) && (
<motion.span
animate={{ filter: "blur(0px)", opacity: 1, scale: 1 }}
className="absolute inset-0 flex items-center justify-center text-accent-foreground"
exit={{ filter: "blur(2px)", opacity: 0, scale: 0.8 }}
initial={{ filter: "blur(2px)", opacity: 0, scale: 0.8 }}
key={state.indeterminate ? "indeterminate" : "checked"}
transition={{ duration: 0.2, ease: [0.86, 0, 0.07, 1] }}
>
{state.indeterminate ? <IndeterminateIcon /> : <CheckmarkIcon />}
</motion.span>
)}
</AnimatePresence>
</span>
)}
/>
</BaseCheckbox.Root>
);
}
function CheckmarkIcon() {
return (
<motion.svg aria-hidden="true" className="size-3.5 sm:size-3" fill="none" viewBox="0 0 14 14">
<motion.path
animate={{ pathLength: 1 }}
d="M3 7.25L5.75 10L11 4"
initial={{ pathLength: 0 }}
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="1.5"
transition={{ duration: 0.2, ease: [0.86, 0, 0.07, 1] }}
/>
</motion.svg>
);
}
function IndeterminateIcon() {
return (
<motion.svg aria-hidden="true" className="size-3.5 sm:size-3" fill="none" viewBox="0 0 14 14">
<motion.path
animate={{ pathLength: 1 }}
d="M3.5 7H10.5"
initial={{ pathLength: 0 }}
stroke="currentColor"
strokeLinecap="round"
strokeWidth="1.5"
transition={{ duration: 0.2, ease: [0.86, 0, 0.07, 1] }}
/>
</motion.svg>
);
}
export { CheckboxGroup, Checkbox };API Reference
Checkbox
This component does not add any props on top of Base UI Checkbox.Root. See the Base UI docs for the full API reference.
CheckboxGroup
This component does not add any props on top of Base UI CheckboxGroup. See the Base UI docs for the full API reference.