blode
uicheckboxsource: ok · refreshed
Checkbox
A control that allows the user to toggle between checked and unchecked states.
npx shadcn add "https://blode.co/ui/r/checkbox.json"free
Where it goes
stats
Interaction
animated-counter
Tags auto-generated by rules on 9/24/2026 — empty means no evidence, not lack of support.
Dependencies
Bundle weight · lightui-primitives@base-ui/react
Files2 · source cached 10/7/2026, 3:06:01 AM
ui/checkbox.tsx
"use client";
import { Checkbox as CheckboxPrimitive } from "@base-ui/react/checkbox";
import * as React from "react";
import { cn } from "@/lib/utils";
import "./checkbox.css";
type CheckedState = boolean | "indeterminate";
export interface CheckboxProps extends Omit<
React.ComponentProps<typeof CheckboxPrimitive.Root>,
"checked" | "defaultChecked" | "indeterminate" | "onCheckedChange"
> {
checked?: CheckedState;
defaultChecked?: CheckedState;
hasError?: boolean;
indeterminate?: boolean;
onCheckedChange?: (checked: CheckedState) => void;
}
const Checkbox = ({
checked,
className,
defaultChecked,
hasError,
indeterminate,
onCheckedChange,
...props
}: CheckboxProps) => {
const resolvedIndeterminate =
indeterminate ?? (checked === "indeterminate" || defaultChecked === "indeterminate");
return (
<CheckboxPrimitive.Root
aria-invalid={hasError || undefined}
checked={checked === "indeterminate" ? false : checked}
className={cn(
"ft-checkbox peer relative inline-flex size-5 shrink-0 cursor-pointer items-center justify-center overflow-hidden rounded-[6px] bg-card align-middle shadow-input transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 data-disabled:cursor-not-allowed data-checked:text-primary-foreground data-indeterminate:text-primary-foreground data-disabled:opacity-50",
className,
)}
data-slot="checkbox"
defaultChecked={defaultChecked === "indeterminate" ? false : defaultChecked}
indeterminate={resolvedIndeterminate}
onCheckedChange={(nextChecked) => onCheckedChange?.(nextChecked)}
render={(renderProps, state) => {
let dataState: "indeterminate" | "checked" | "unchecked" = "unchecked";
if (state.indeterminate) {
dataState = "indeterminate";
} else if (state.checked) {
dataState = "checked";
}
return <span {...renderProps} data-state={dataState} />;
}}
{...props}
>
<CheckboxPrimitive.Indicator
className="pointer-events-none flex items-center justify-center text-current"
data-slot="checkbox-indicator"
keepMounted
>
<svg aria-hidden="true" className="z-10 h-3 w-4" role="presentation" viewBox="0 0 17 18">
<polyline
className="ft-checkbox-polyline"
fill="none"
points="1 9 7 14 15 4"
stroke="currentColor"
strokeDasharray={22}
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
/>
<line
className="ft-checkbox-line"
stroke="currentColor"
strokeLinecap="round"
strokeWidth={2}
x1="3"
x2="13"
y1="9"
y2="9"
/>
</svg>
</CheckboxPrimitive.Indicator>
</CheckboxPrimitive.Root>
);
};
export { Checkbox };
ui/checkbox.css
.ft-checkbox[data-state="checked"] .ft-checkbox-polyline {
stroke-dashoffset: 44;
transition: stroke-dashoffset 250ms linear 0.2s;
}
.ft-checkbox:not([data-state="checked"]) .ft-checkbox-polyline {
stroke-dashoffset: 66;
}
.ft-checkbox .ft-checkbox-line {
opacity: 0;
transform: scaleX(0);
transform-origin: center;
transition:
opacity 250ms ease,
transform 250ms ease;
}
.ft-checkbox[data-state="indeterminate"] .ft-checkbox-line {
opacity: 1;
transform: scaleX(1);
transition:
opacity 250ms ease 0.1s,
transform 250ms ease 0.1s;
}
.ft-checkbox[data-state="indeterminate"] .ft-checkbox-polyline {
opacity: 0;
}
.ft-checkbox::after {
position: absolute;
inset: 0;
content: "";
background-color: var(--primary);
border-radius: 6px;
opacity: 0;
transform-origin: center;
scale: 0.5;
transition: all 200ms linear;
}
.ft-checkbox[data-state="checked"]::after,
.ft-checkbox[data-state="indeterminate"]::after {
opacity: 1;
scale: 1;
}
.ft-checkbox[data-state="checked"]::before,
.ft-checkbox[data-state="indeterminate"]::before {
border-color: var(--primary);
}
.ft-checkbox::before {
position: absolute;
inset: 0;
content: "";
border: 1px solid var(--input);
border-radius: 6px;
transform-origin: center;
transition: all;
}
.ft-checkbox:hover::before {
border-color: var(--input-hover, var(--input));
}