38 lines
1.4 KiB
TypeScript
38 lines
1.4 KiB
TypeScript
import { Check } from "lucide-react";
|
|
import type { ReactNode } from "react";
|
|
|
|
// A pill-shaped on/off toggle button for filters (cuisines, styles, appliances…).
|
|
// Includes a visible Check icon when pressed so state never relies on color alone.
|
|
|
|
interface ChipProps {
|
|
pressed: boolean;
|
|
onClick: () => void;
|
|
children: ReactNode;
|
|
/** "sm" for dense filter rows, "md" for settings panels. */
|
|
size?: "sm" | "md";
|
|
/** Dashed outline when off: tells a second filter row apart from the first. */
|
|
dashed?: boolean;
|
|
}
|
|
|
|
const SIZES = {
|
|
sm: "min-h-8 px-2.5 py-1 text-xs gap-1.5",
|
|
md: "min-h-9 px-3.5 py-1.5 text-sm gap-1.5",
|
|
};
|
|
|
|
export function Chip({ pressed, onClick, children, size = "md", dashed = false }: ChipProps) {
|
|
const look = pressed
|
|
? "border-selected-line bg-selected font-medium text-ink shadow-2xs"
|
|
: `border-line-strong bg-surface text-ink-muted hover:border-ink-muted hover:bg-raised hover:text-ink ${dashed ? "border-dashed" : ""}`;
|
|
|
|
return (
|
|
<button
|
|
type="button"
|
|
aria-pressed={pressed}
|
|
onClick={onClick}
|
|
className={`trim-cap inline-flex items-center rounded-full border transition-colors ${SIZES[size]} ${look}`}
|
|
>
|
|
{pressed && <Check className="size-3.5 shrink-0 text-brand-300" strokeWidth={2.5} aria-hidden />}
|
|
<span className="inline-flex items-center gap-1.5">{children}</span>
|
|
</button>
|
|
);
|
|
}
|