Make the react component for those pills. can show a circle animating in from right overlaying a bit to show the x on hover wdyt?Use tailwind cssimport React from "react";/** * Pills with hover reveal delete circle. * Tailwind only. No extra libs. * * How it works: * - The pill is a group with relative and overflow-visible. * - A circular <button> sits absolutely at the right edge, a bit outside. * - It starts hidden and translated to the right. * - On hover/focus of the pill, the circle slides in and shows the X. /export type Pill = { id: string | number; label: string;};export function PillsDemo() { const [items, setItems] = React.useState<Pill[]>([ { id: 1, label: "Minimal" }, { id: 2, label: "Hypnotic" }, { id: 3, label: "Underground" }, { id: 4, label: "Synth" }, { id: 5, label: "Clean kick" }, { id: 6, label: "Tribal" }, { id: 7, label: "Echo" }, ]); return ( <div className="flex flex-wrap gap-3 p-4 bg-white"> {items.map((it) => ( <PillItem key={it.id} label={it.label} onRemove={() => setItems((prev) => prev.filter((p) => p.id !== it.id))} /> ))} </div> );}/* Single pill /export function PillItem({ label, onRemove }: { label: string; onRemove?: () => void }) { return ( <div className="group relative inline-flex items-center rounded-full border border-black/10 bg-white px-5 py-2 text-sm font-medium text-black shadow-sm transition-colors duration-200 hover:border-black/20 focus-within:border-black/30" > <span className="select-none">{label}</span> {/ Circle with X. It overlaps a bit to the right. /} {onRemove && ( <button type="button" onClick={onRemove} aria-label={Remove ${label}} className="absolute right-[-10px] top-1/2 flex h-7 w-7 -translate-y-1/2 translate-x-3/4 items-center justify-center rounded-full bg-black text-white shadow-md ring-1 ring-black/10 opacity-0 transition-all duration-300 ease-out motion-reduce:transition-none group-hover:translate-x-0 group-hover:opacity-100 focus-visible:translate-x-0 focus-visible:opacity-100" > <XIcon className="h-3.5 w-3.5" /> </button> )} </div> );}function XIcon({ className = "" }: { className?: string }) { return ( <svg className={className} viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" aria-hidden > <line x1="18" y1="6" x2="6" y2="18" /> <line x1="6" y1="6" x2="18" y2="18" /> </svg> );}/* * Optional: a compact version /export function PillItemSm({ label, onRemove }: { label: string; onRemove?: () => void }) { return ( <div className="group relative inline-flex items-center rounded-full border border-black/10 bg-white px-4 py-1.5 text-[15px] text-black shadow-sm"> <span className="select-none">{label}</span> {onRemove && ( <button type="button" onClick={onRemove} aria-label={Remove ${label}} className="absolute right-[-8px] top-1/2 flex h-6 w-6 -translate-y-1/2 translate-x-2/3 items-center justify-center rounded-full bg-black text-white shadow ring-1 ring-black/10 opacity-0 transition-all duration-300 ease-out motion-reduce:transition-none group-hover:translate-x-0 group-hover:opacity-100 focus-visible:translate-x-0 focus-visible:opacity-100" > <XIcon className="h-3 w-3" /> </button> )} </div> );}/* * Usage: * <PillsDemo /> * or * <PillItem label="Minimal" onRemove={() => {}} /> */
I'll create the pills component with the smooth hover animation you described! The design looks clean with the circular delete button sliding in from the right on hover.
Perfect! I've created the pills component with the smooth hover animation you wanted. Here's what makes it work:
Key Features:
Animation Details:
translate-x-3/4 (75% to the right) and opacity-0translate-x-0 and opacity-100duration-300 and ease-out for smooth motionThe component includes both regular and small (PillItemSm) versions, and you can easily customize the colors, sizes, and animation timing by adjusting the Tailwind classes!
Perfect! Now the X button:
h-full aspect-square to match the pill's height exactlyoverflow-hidden so the button slides from withintranslate-x-full to start completely hidden, then slides to translate-x-0 on hoverThe animation now feels much more integrated - like the delete circle is emerging from inside the pill itself rather than floating above it!