Chip
Interactive tags for filters, categories, and multi-select. Unlike Badge (display-only), Chips are pressable and selectable.
import { Chip } from "@/components/ui/chip";
<Chip variant="default">React Native</Chip>
<Chip variant="secondary">TypeScript</Chip>
<Chip variant="outline">NativeWind</Chip>Installation
npx @aniui/cli add chipVariants
<Chip variant="default">Default</Chip>
<Chip variant="secondary">Secondary</Chip>
<Chip variant="outline">Outline</Chip>
<Chip variant="destructive">Destructive</Chip>Sizes
<Chip size="sm">Small</Chip>
<Chip size="md">Medium</Chip>
<Chip size="lg">Large</Chip>Selectable
Use the selected prop for filter chips. Selected chips switch to the default (filled) variant automatically.
const [selected, setSelected] = useState<string[]>(["react-native"]);
const toggle = (id: string) =>
setSelected((s) => s.includes(id) ? s.filter((x) => x !== id) : [...s, id]);
<Chip selected={selected.includes("react-native")} onPress={() => toggle("react-native")}>React Native</Chip>
<Chip selected={selected.includes("expo")} onPress={() => toggle("expo")}>Expo</Chip>
<Chip selected={selected.includes("nativewind")} onPress={() => toggle("nativewind")}>NativeWind</Chip>Closable
Add an onClose handler to show a remove button.
<Chip onClose={() => console.log("removed")}>Removable</Chip>
<Chip variant="secondary" onClose={() => {}}>Tag</Chip>Props
PropTypeDefault
variant"default" | "secondary" | "outline" | "destructive""outline"size"sm" | "md" | "lg""md"childrenstring—selectedbooleanfalseonClose() => void—textClassNamestring—classNamestring—Source
components/ui/chip.tsx
import React from "react";
import { View, Text, Pressable } from "react-native";
import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
const chipVariants = cva(
"flex-row items-center rounded-full min-h-8",
{
variants: {
variant: {
default: "bg-primary",
secondary: "bg-secondary",
outline: "border border-input bg-transparent",
destructive: "bg-destructive",
},
size: {
sm: "px-2.5 py-1 gap-1",
md: "px-3 py-1.5 gap-1.5",
lg: "px-4 py-2 gap-2",
},
},
defaultVariants: { variant: "default", size: "md" },
}
);
const chipTextVariants = cva("font-medium", {
variants: {
variant: {
default: "text-primary-foreground",
secondary: "text-secondary-foreground",
outline: "text-foreground",
destructive: "text-destructive-foreground",
},
size: { sm: "text-xs", md: "text-sm", lg: "text-base" },
},
defaultVariants: { variant: "default", size: "md" },
});
export interface ChipProps
extends React.ComponentPropsWithoutRef<typeof Pressable>,
VariantProps<typeof chipVariants> {
className?: string;
textClassName?: string;
children: string;
selected?: boolean;
onClose?: () => void;
}
export function Chip({ variant, size, className, textClassName, children, selected, onClose, ...props }: ChipProps) {
const v = selected ? "default" : (variant ?? "outline");
return (
<Pressable className={cn(chipVariants({ variant: v, size }), className)} accessible={true} accessibilityRole="button" accessibilityState={{ selected }} {...props}>
<Text className={cn(chipTextVariants({ variant: v, size }), textClassName)}>{children}</Text>
{onClose && (
<Pressable onPress={onClose} accessibilityRole="button" accessibilityLabel={`Remove ${children}`} className="ml-0.5">
<Text className={cn("text-xs", v === "outline" ? "text-muted-foreground" : chipTextVariants({ variant: v, size: "sm" }))}>✕</Text>
</Pressable>
)}
</Pressable>
);
}