Filter chips
Pill-shaped filters you can switch on and off, each one showing a small check mark as it activates.
Settings
Code
import { useState } from "react";
import { AnimatePresence, motion } from "framer-motion";
import { Check } from "lucide-react";
const sizeMap = {
sm: { pad: "px-3 py-1.5", text: "text-xs" },
md: { pad: "px-4 py-2", text: "text-sm" },
lg: { pad: "px-5 py-2.5", text: "text-base" },
} as const;
interface FilterChipsProps {
accent?: string;
size?: keyof typeof sizeMap;
options?: string[];
value?: string[];
onChange?: (value: string[]) => void;
}
export default function FilterChips({
accent = "#0071e3",
size = "md",
options = ["Design", "Code", "Audio", "Video", "3D"],
value,
onChange,
}: FilterChipsProps) {
const [internal, setInternal] = useState<string[]>(options.slice(0, 1));
const active = value ?? internal;
const s = sizeMap[size];
const toggle = (o: string) => {
const next = active.includes(o) ? active.filter((x) => x !== o) : [...active, o];
if (value === undefined) setInternal(next);
onChange?.(next);
};
return (
<div className="flex w-full max-w-md flex-wrap justify-center gap-2">
{options.map((o) => {
const on = active.includes(o);
return (
<motion.button
key={o}
type="button"
aria-pressed={on}
whileTap={{ scale: 0.94 }}
onClick={() => toggle(o)}
className={`flex items-center gap-1.5 rounded-full border font-medium transition-colors ${s.pad} ${s.text}`}
style={{
borderColor: on ? accent : "oklch(1 0 0 / 14%)",
backgroundColor: on ? `${accent}22` : "transparent",
color: on ? accent : undefined,
}}
>
<AnimatePresence initial={false}>
{on && (
<motion.span
initial={{ width: 0, opacity: 0 }}
animate={{ width: "auto", opacity: 1 }}
exit={{ width: 0, opacity: 0 }}
className="overflow-hidden"
>
<Check className="h-3.5 w-3.5" />
</motion.span>
)}
</AnimatePresence>
{o}
</motion.button>
);
})}
</div>
);
}
Prompt for AI
Paste it into ChatGPT, Claude or Cursor and it will adapt the block to your project with these settings, even if you don’t use React.
More in Filters
Where to use it
Chips are the quickest way to let people narrow a list without opening a menu: cuisine types on a recipe site, sizes in a clothing shop, topics on a blog or skills on a job board. These filter chips allow several choices at once, and the check mark makes it obvious what is switched on.
They work best with up to eight short labels, one or two words each. If you have dozens of options, move them into a dropdown with search instead. Use the small size inside cards and the large one on mobile, where fingers need room.