fix(ui): unify checkbox styles

This commit is contained in:
saladday committed 2026-08-06 10:28:09 -04:00
1 parent 413c09e079
commit 0257f2953d
1 file changed
+55 -26
+55 -26
View File
@@ -1,33 +1,62 @@
import * as React from "react";
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
import { Check, Minus } from "lucide-react";
import { cn } from "@/lib/utils";
const Checkbox = React.forwardRef<
React.ElementRef<typeof CheckboxPrimitive.Root>,
React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
>(({ className, ...props }, ref) => (
<CheckboxPrimitive.Root
ref={ref}
className={cn(
"grid place-content-center peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground",
"data-[state=indeterminate]:bg-primary data-[state=indeterminate]:text-primary-foreground",
type CheckedState = boolean | "indeterminate";
interface CheckboxProps
extends Omit<
React.InputHTMLAttributes<HTMLInputElement>,
"checked" | "type"
> {
checked?: CheckedState;
onCheckedChange?: (checked: boolean) => void;
}
const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
(
{
className,
)}
{...props}
>
<CheckboxPrimitive.Indicator
className={cn("grid place-content-center text-current")}
>
{props.checked === "indeterminate" ? (
<Minus className="h-4 w-4" />
) : (
<Check className="h-4 w-4" />
)}
</CheckboxPrimitive.Indicator>
</CheckboxPrimitive.Root>
));
Checkbox.displayName = CheckboxPrimitive.Root.displayName;
checked,
onChange,
onCheckedChange,
"aria-checked": ariaChecked,
...props
},
ref,
) => {
const inputRef = React.useRef<HTMLInputElement>(null);
const isIndeterminate = checked === "indeterminate";
React.useImperativeHandle(ref, () => inputRef.current as HTMLInputElement);
React.useLayoutEffect(() => {
if (inputRef.current) {
inputRef.current.indeterminate = isIndeterminate;
}
});
return (
<input
{...props}
ref={inputRef}
type="checkbox"
checked={isIndeterminate ? false : checked}
aria-checked={isIndeterminate ? "mixed" : ariaChecked}
onChange={(event) => {
onChange?.(event);
onCheckedChange?.(event.target.checked);
}}
className={cn(
"w-4 h-4 text-blue-500 bg-white dark:bg-gray-800 border-border-default rounded focus:ring-blue-500 dark:focus:ring-blue-400 focus:ring-2",
className,
)}
/>
);
},
);
Checkbox.displayName = "Checkbox";
export { Checkbox };
export type { CheckboxProps, CheckedState };