Checkbox
A control that allows the user to toggle between checked and not checked.
Demo
Dependencies
lucide-reactclsxtailwind-merge
Props
This is a base primitive. It accepts standard HTML attributes plus className for styling via cn().
Source
"use client";
import { useState, useCallback } from "react";
import { cn } from "@/lib/utils";
import { Check } from "lucide-react";
export interface CheckboxProps {
checked?: boolean;
defaultChecked?: boolean;
onCheckedChange?: (checked: boolean) => void;
disabled?: boolean;
className?: string;
}
export function Checkbox({
checked: controlledChecked,
defaultChecked = false,
onCheckedChange,
disabled,
className,
}: CheckboxProps) {
const [internalChecked, setInternalChecked] = useState(defaultChecked);
const isControlled = controlledChecked !== undefined;
const checked = isControlled ? controlledChecked : internalChecked;
const handleClick = useCallback(() => {
if (disabled) return;
const next = !checked;
if (!isControlled) setInternalChecked(next);
onCheckedChange?.(next);
}, [checked, disabled, isControlled, onCheckedChange]);
return (
<button
role="checkbox"
aria-checked={checked}
disabled={disabled}
onClick={handleClick}
className={cn(
"peer flex h-4 w-4 shrink-0 items-center justify-center rounded-sm border border-gray-300 bg-white transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-gray-400 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
checked && "border-gray-900 bg-gray-900 text-white",
className,
)}
>
{checked && <Check className="h-3 w-3" />}
</button>
);
}
CLI
npx genui add checkbox