Docs/Components/Checkbox

Checkbox

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

Installation

Install the component Checkbox in your project using the CLI.

Checkbox.tsx

pnpm dlx behsseui@latest add Checkbox

Install the component manually.

Create a ui folder at the root of the project, then a component folder inside it, and finally a Checkbox.tsx file in that folder.

Copy and paste the following code into your project.

ui/components/Checkbox.tsx

1"use client"
2
3import { useState, useId, forwardRef } from "react"
4import { cn } from "@/lib/utils"
5import Check from "@/ui/icons/Check"
6
7interface CheckboxProps {
8 checked?: boolean
9 defaultChecked?: boolean
10 onCheckedChange?: (checked: boolean) => void
11 disabled?: boolean
12 id?: string
13 name?: string
14 value?: string
15 className?: string
16 label?: string
17}
18
19const Checkbox = forwardRef<HTMLButtonElement, CheckboxProps>(
20 (
21 {
22 checked: controlledChecked,
23 defaultChecked = false,
24 onCheckedChange,
25 disabled = false,
26 id: providedId,
27 name,
28 value,
29 className,
30 label,
31 },
32 ref
33 ) => {
34 const generatedId = useId()
35 const id = providedId ?? generatedId
36
37 // Internal state for uncontrolled mode
38 const [internalChecked, setInternalChecked] = useState(defaultChecked)
39
40 // Determine if controlled or uncontrolled
41 const isControlled = controlledChecked !== undefined
42 const isChecked = isControlled ? controlledChecked : internalChecked
43
44 const handleClick = () => {
45 if (disabled) return
46
47 const newChecked = !isChecked
48
49 // Update internal state (for uncontrolled mode)
50 if (!isControlled) {
51 setInternalChecked(newChecked)
52 }
53
54 // Call onCheckedChange callback if provided
55 onCheckedChange?.(newChecked)
56 }
57
58 const handleKeyDown = (e: React.KeyboardEvent) => {
59 if (e.key === " " || e.key === "Enter") {
60 e.preventDefault()
61 handleClick()
62 }
63 }
64
65 return (
66 <div className={cn("flex items-center gap-2", className)}>
67 <button
68 ref={ref}
69 type="button"
70 role="checkbox"
71 aria-checked={isChecked}
72 aria-disabled={disabled}
73 id={id}
74 data-state={isChecked ? "checked" : "unchecked"}
75 data-disabled={disabled ? "" : undefined}
76 disabled={disabled}
77 onClick={handleClick}
78 onKeyDown={handleKeyDown}
79 className={cn(
80 "peer h-4 w-4 shrink-0 rounded-[3px] border border-primary",
81 "focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
82 "transition-colors",
83 isChecked && "bg-primary text-primary-foreground",
84 disabled && "cursor-not-allowed opacity-50"
85 )}
86 >
87 {isChecked && (
88 <Check className="h-3.5 w-3.5 text-primary-foreground" />
89 )}
90 </button>
91 {/* Hidden input for form submission */}
92 <input
93 type="checkbox"
94 name={name}
95 value={value}
96 checked={isChecked}
97 disabled={disabled}
98 onChange={() => {}}
99 className="sr-only"
100 tabIndex={-1}
101 aria-hidden="true"
102 />
103 {label && (
104 <label
105 htmlFor={id}
106 className={cn(
107 "text-sm font-medium leading-none cursor-pointer",
108 "peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
109 )}
110 >
111 {label}
112 </label>
113 )}
114 </div>
115 )
116 }
117)
118
119Checkbox.displayName = "Checkbox"
120
121export { Checkbox }
122

Usages

Different variants and use cases for the Checkbox component.

Default

A basic checkbox without a label.

Default.tsx

<Checkbox />

With Label

A checkbox with an associated label.

With Label.tsx

<Checkbox label="Accept terms and conditions" />

Checked

A checkbox that starts in a checked state.

Checked.tsx

<Checkbox defaultChecked label="I agree" />

Disabled

A disabled checkbox that cannot be interacted with.

Disabled.tsx

<Checkbox disabled label="Disabled" />

Disabled Checked

A disabled checkbox in a checked state.

Disabled Checked.tsx

<Checkbox disabled defaultChecked label="Disabled checked" />

Group

Multiple checkboxes grouped together allowing users to select multiple options.

Group.tsx

<div className="flex flex-col gap-3">
  <Checkbox label="Option 1" />
  <Checkbox label="Option 2" />
  <Checkbox label="Option 3" />
</div>