Checkbox
A binary toggle for consent boxes, multi-select filters, and bulk row selection — with the neobrutalist borders-and-shadows treatment.
"use client"
import { Checkbox } from "@/components/ui/checkbox"The checkbox is the standard control for binary choices — checked, unchecked, or indeterminate for partial selections. Built on the Base UI Checkbox primitive and styled to the neobrutalist recipe: thick borders, hard shadows, and bold type.
Reach for it when:
- Terms and consent — the "I agree" box in signup and checkout flows, submitted with the form.
- Multi-select filters — categories, tags, or price ranges in a sidebar where any combination is valid.
- Bulk selection in tables — per-row checkboxes plus an indeterminate select-all in the header.
Installation#
pnpm dlx shadcn@latest add https://neobrutalism.com/r/base/checkbox.jsonnpx shadcn@latest add https://neobrutalism.com/r/base/checkbox.jsonyarn dlx shadcn@latest add https://neobrutalism.com/r/base/checkbox.jsonbunx --bun shadcn@latest add https://neobrutalism.com/r/base/checkbox.json
Install the following dependencies:
pnpm add @base-ui/reactnpm install @base-ui/reactyarn add @base-ui/reactbun add @base-ui/react
Copy and paste the following code into your project.
"use client"
import * as React from "react"
import { CheckIcon } from "lucide-react"
import { Checkbox as CheckboxPrimitive } from "radix-ui"
import { cn } from "@/lib/utils"
function Checkbox({
className,
...props
}: React.ComponentProps<typeof CheckboxPrimitive.Root>) {
return (
<CheckboxPrimitive.Root
data-slot="checkbox"
className={cn(
"peer relative flex size-5 shrink-0 items-center justify-center rounded border-2 bg-input shadow-sm transition-colors outline-none group-has-disabled/field:opacity-50 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive data-checked:border-border data-checked:bg-primary data-checked:text-primary-foreground",
className
)}
{...props}
>
<CheckboxPrimitive.Indicator
data-slot="checkbox-indicator"
className="grid place-content-center text-current transition-none [&>svg]:size-3.5"
>
<CheckIcon />
</CheckboxPrimitive.Indicator>
</CheckboxPrimitive.Root>
)
}
export { Checkbox }
Update the import paths to match your project setup.
Usage#
import { Checkbox } from "@/components/ui/checkbox"<Checkbox />Checked State#
Use defaultChecked for uncontrolled checkboxes, or checked and
onCheckedChange to control the state.
import * as React from "react"
export function Example() {
const [checked, setChecked] = React.useState(false)
return <Checkbox checked={checked} onCheckedChange={setChecked} />
}Invalid State#
Set aria-invalid on the checkbox and data-invalid on the field wrapper to
show the invalid styles.
import { Checkbox } from "@/components/ui/checkbox"
import { Field, FieldGroup, FieldLabel } from "@/components/ui/field"
Examples#
Basic#
Pair the checkbox with Field and FieldLabel for proper layout and labeling.
import { Checkbox } from "@/components/ui/checkbox"
import { Field, FieldGroup, FieldLabel } from "@/components/ui/field"
Description#
Use FieldContent and FieldDescription for helper text.
import { Checkbox } from "@/components/ui/checkbox"
import {
Field,Disabled#
Use the disabled prop to prevent interaction and add the data-disabled attribute to the <Field> component for disabled styles.
import { Checkbox } from "@/components/ui/checkbox"
import { Field, FieldGroup, FieldLabel } from "@/components/ui/field"
Group#
Use multiple fields to create a checkbox list.
import { Checkbox } from "@/components/ui/checkbox"
import {
Field,Table#
"use client"
import * as React from "react"RTL#
To enable RTL support in Neobrutalism.com, see the RTL configuration guide.
"use client"
import * as React from "react"Accessibility#
The checkbox follows the WAI-ARIA Checkbox pattern: the primitive renders a role="checkbox" element with aria-checked (including "mixed" for the indeterminate state) and syncs a hidden native input so the value submits with forms.
Keyboard interactions:
| Key | Action |
|---|---|
Tab / Shift + Tab | Move focus to or away from the checkbox |
Space | Toggle the checked state (indeterminate → checked) |
Enter does not toggle a checkbox — that is per the ARIA pattern, not a bug.
API Reference#
See the Base UI documentation for more information.