44 lines
1.3 KiB
TypeScript
44 lines
1.3 KiB
TypeScript
"use client";
|
|
|
|
import { Check } from "lucide-react";
|
|
import { useTheme } from "next-themes";
|
|
|
|
import { cn } from "@/lib/utils";
|
|
import { GROUP_COLORS, type GroupColorKey } from "@/lib/colors";
|
|
|
|
export function ColorSwatchPicker({
|
|
value,
|
|
onChange,
|
|
}: {
|
|
value: GroupColorKey;
|
|
onChange: (key: GroupColorKey) => void;
|
|
}) {
|
|
const { resolvedTheme } = useTheme();
|
|
const isDark = resolvedTheme === "dark";
|
|
|
|
return (
|
|
<div role="radiogroup" aria-label="Card color" className="flex flex-wrap gap-2">
|
|
{GROUP_COLORS.map((color) => {
|
|
const selected = color.key === value;
|
|
return (
|
|
<button
|
|
key={color.key}
|
|
type="button"
|
|
role="radio"
|
|
aria-checked={selected}
|
|
aria-label={color.label}
|
|
onClick={() => onChange(color.key)}
|
|
className={cn(
|
|
"flex size-8 items-center justify-center rounded-full ring-offset-2 ring-offset-background transition-transform hover:scale-110",
|
|
selected && "ring-2 ring-foreground"
|
|
)}
|
|
style={{ backgroundColor: isDark ? color.dark : color.light }}
|
|
>
|
|
{selected && <Check className="size-4 text-white drop-shadow" />}
|
|
</button>
|
|
);
|
|
})}
|
|
</div>
|
|
);
|
|
}
|