All Taste components
Inputs
Colour swatch picker
Pick one colour from a set of swatches, or add your own.
selected ring · custom swatch · keyboard (arrow keys)
Label colourBrand
Used for the “Festive menu” tag on your orders."use client";
import { Plus } from "lucide-react";
import { cn } from "@/lib/utils";
// Full class names (fill + ring) so Tailwind can see them; all come from your Taste preset.
export const SWATCHES = [
{ name: "Brand", fill: "bg-brand-600", ring: "border-brand-600" },
{ name: "Brand light", fill: "bg-brand-300", ring: "border-brand-300" },
{ name: "Blue", fill: "bg-info", ring: "border-info" },
{ name: "Green", fill: "bg-success", ring: "border-success" },
{ name: "Amber", fill: "bg-warning", ring: "border-warning" },
{ name: "Red", fill: "bg-danger", ring: "border-danger" },
{ name: "Grey", fill: "bg-neutral-400", ring: "border-neutral-400" },
{ name: "Ink", fill: "bg-neutral-900", ring: "border-neutral-900" },
];
/* Native radios: Tab enters the group, arrow keys move the selection. */
export function SwatchPicker({ label, value, onChange, onAddCustom, swatches = SWATCHES }:
{ label: string; value: string; onChange: (name: string) => void; onAddCustom?: () => void; swatches?: typeof SWATCHES }) {
return (
<fieldset className="grid gap-2">
<legend className="mb-2 flex w-full items-baseline justify-between text-[13px] font-medium text-fg">
{label}
<span className="font-normal text-fg-muted">{value}</span>
</legend>
<div className="flex flex-wrap gap-2.5 p-1">
{swatches.map((s) => (
<label key={s.name} title={s.name} className="relative size-8 cursor-pointer">
<input
type="radio"
name={label}
value={s.name}
aria-label={s.name}
checked={value === s.name}
onChange={() => onChange(s.name)}
className={cn(
"peer absolute inset-0 m-0 size-full cursor-pointer appearance-none rounded ring-1 ring-inset ring-fg/15 transition",
"focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-[6px] focus-visible:outline-ring",
s.fill,
)}
/>
{/* Selected: a gap in the page colour, then a ring in the swatch's own colour. */}
<span aria-hidden className={cn("pointer-events-none absolute -inset-1 hidden rounded-lg border-2 peer-checked:block", s.ring)} />
</label>
))}
{onAddCustom && (
<button type="button" aria-label="Add a custom colour" onClick={onAddCustom}
className="grid size-8 place-items-center rounded border-[1.5px] border-dashed border-border-strong text-fg-muted transition hover:border-fg-subtle hover:text-fg">
<Plus className="size-4" />
</button>
)}
</div>
</fieldset>
);
}
The code uses the Taste Tailwind preset. Make yours on the Taste page with Export my system.