Chip
Standalone assist, filter, and input chips.
Preview
import { Chip } from "@/components/ui/Chip";
export function ChipDemo() {
return <Chip>Suggest a reply</Chip>;
}Installation
Make sure that namespace is set in your component.json file. Namespace docs: Learn more about namespaces
pnpm dlx shadcn@latest add @aura/chipManual
Install the following dependencies:
pnpm install @radix-ui/react-icons class-variance-authorityCopy and paste the class names utility into your utils/class-names.ts file.
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
Copy and paste the Chip component into your components/ui/Chip.tsx file.
"use client";
import * as React from "react";
import { cva, type VariantProps } from "class-variance-authority";
import { CheckIcon, Cross2Icon } from "@radix-ui/react-icons";
import { cn } from "@/utils/class-names";
const chipVariants = cva(
"inline-flex items-center gap-0.5 rounded-full border px-1.5 py-0.5 transition focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent-8 motion-reduce:transition-none",
{
variants: {
variant: {
assist:
"border-gray-6 bg-gray-1 text-gray-12 hover:bg-gray-3",
filter:
"border-gray-6 bg-gray-2 text-gray-12 hover:bg-gray-3 data-[selected=true]:border-transparent data-[selected=true]:bg-gray-12 data-[selected=true]:text-gray-1",
input: "border-gray-6 bg-gray-3 text-gray-12",
},
},
defaultVariants: {
variant: "assist",
},
},
);
type ChipProps = React.ComponentProps<"button"> &
VariantProps<typeof chipVariants> & {
selected?: boolean;
onRemove?: () => void;
removeLabel?: string;
};
function Chip({
className,
variant = "assist",
selected,
onRemove,
removeLabel = "Remove",
children,
...props
}: ChipProps) {
if (variant === "input") {
return (
<span
data-slot="chip"
data-variant="input"
className={cn(chipVariants({ variant }), className)}
>
<span>{children}</span>
<button
type="button"
aria-label={removeLabel}
className="inline-flex size-2 items-center justify-center rounded-full hover:bg-gray-5 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-accent-8"
onClick={onRemove}
>
<Cross2Icon className="icon" />
</button>
</span>
);
}
return (
<button
type="button"
data-slot="chip"
data-variant={variant}
data-selected={selected ? "true" : "false"}
aria-pressed={variant === "filter" ? Boolean(selected) : undefined}
className={cn(chipVariants({ variant }), className)}
{...props}
>
{variant === "filter" && selected ? <CheckIcon className="icon" /> : null}
{children}
</button>
);
}
export { Chip, chipVariants };
Usage
Filter
export const Filter = () => {
return (
<div className="flex flex-wrap gap-0.5">
<Chip variant="filter" selected>
Open
</Chip>
<Chip variant="filter">Closed</Chip>
</div>
);
};Input
export const Input = () => {
return (
<Chip variant="input" removeLabel="Remove design">
Design
</Chip>
);
};