Organize/components/board/todo-checkbox.tsx

61 lines
2.0 KiB
TypeScript

"use client";
import { Checkbox as CheckboxPrimitive } from "@base-ui/react/checkbox";
import { cn } from "@/lib/utils";
import { HandDrawnCheck } from "@/components/board/hand-drawn-check";
/**
* The to-do checkbox for a group card: its stroke matches the card's own
* accent color instead of the neutral theme border, and its checkmark is a
* solid, slightly-oversized "hand-drawn" tick (rendered white on dark
* theme, black on light theme) that pokes just above the box.
*/
export function TodoCheckbox({
checked,
onCheckedChange,
accentColor,
isDark,
className,
"aria-label": ariaLabel,
}: {
checked: boolean;
onCheckedChange: (checked: boolean) => void;
accentColor: string;
isDark: boolean;
className?: string;
"aria-label": string;
}) {
const checkColor = isDark ? "#ffffff" : "#000000";
return (
<CheckboxPrimitive.Root
checked={checked}
onCheckedChange={onCheckedChange}
data-todo-checkbox=""
aria-label={ariaLabel}
style={{
borderColor: accentColor,
backgroundColor: checked ? accentColor : "transparent",
}}
className={cn(
"relative flex size-4 shrink-0 items-center justify-center overflow-visible rounded-[4px] border-2 outline-none transition-colors",
"focus-visible:ring-3 focus-visible:ring-ring/50",
"disabled:cursor-not-allowed disabled:opacity-50",
className
)}
>
<CheckboxPrimitive.Indicator
className="pointer-events-none absolute inset-0"
style={{ color: checkColor }}
>
{/* The check's own path dips a couple of viewBox units above y=0,
so only its top tip overhangs the box -- the sides and bottom
stay flush, keeping the effect to "pokes out the top" rather
than the icon just being oversized on every edge. */}
<HandDrawnCheck className="size-full overflow-visible drop-shadow-[0_1px_0.5px_rgba(0,0,0,0.35)]" />
</CheckboxPrimitive.Indicator>
</CheckboxPrimitive.Root>
);
}