Chip
React data-displayCompact, removable tag — typically used inside `tags-input` or as a filter pill. Seven variants (`default`, `filled`, `outlined`, `elevated`, `success`, `warning`, `destructive`), three sizes, and an optional close button.
Also available for Vue ->Installation
$ pnpm dlx shadcn@latest add https://react.uipkge.dev/r/react/chip.json$ npx shadcn@latest add https://react.uipkge.dev/r/react/chip.json$ yarn dlx shadcn@latest add https://react.uipkge.dev/r/react/chip.json$ bunx shadcn@latest add https://react.uipkge.dev/r/react/chip.json
Or with the named registry:
npx shadcn@latest add @uipkge-react/chip
Examples
Props
| Name | Type / Values | Default | Required |
|---|---|---|---|
variant | 'default''filled''outlined''elevated''success''warning''destructive' | default | optional |
size | 'sm''default''lg' | default | optional |
closable | boolean | — | optional |
onClose | () => void | — | optional |
Dependencies
Files (3)
-
components/ui/chip/chip.tsx 3 kB
'use client' import * as React from 'react' import { X } from 'lucide-react' import { cn } from '@/lib/utils' import { chipVariants, type ChipVariants } from './chip.variants' export interface ChipProps extends Omit<React.HTMLAttributes<HTMLSpanElement>, 'onClose'>, ChipVariants { closable?: boolean onClose?: () => void } const Chip = React.forwardRef<HTMLSpanElement, ChipProps>( ({ className, variant, size, closable, onClose, children, ...props }, ref) => ( <span ref={ref} className={cn(chipVariants({ variant, size }), className)} {...props}> {children} {closable ? ( <button type="button" aria-label={`Remove ${children ? '' : 'item'}`} className="focus-visible:ring-ring hover:bg-foreground/10 ml-0.5 inline-flex min-h-6 min-w-6 items-center justify-center rounded-full focus-visible:ring-1 focus-visible:outline-none" onClick={(e) => { e.stopPropagation() onClose?.() }} > <X className="size-3" aria-hidden="true" /> </button> ) : null} </span> ), ) Chip.displayName = 'Chip' export interface ChipGroupRenderProps { selected: string[] multiple: boolean filter: boolean isSelected: (value: string) => boolean toggle: (value: string) => void } export interface ChipGroupProps { className?: string selected?: string[] multiple?: boolean filter?: boolean column?: boolean mandatory?: boolean max?: number disabled?: boolean onSelectedChange?: (value: string[]) => void children?: (props: ChipGroupRenderProps) => React.ReactNode } const ChipGroup = React.forwardRef<HTMLDivElement, ChipGroupProps>( ( { className, selected = [], multiple = false, filter = false, column = false, mandatory = false, max, disabled = false, onSelectedChange, children, }, ref, ) => { const isSelected = (value: string) => selected.includes(value) const toggle = (value: string) => { if (disabled) return let newSelected: string[] if (multiple) { if (isSelected(value)) { newSelected = selected.filter((v) => v !== value) } else { if (max && selected.length >= max) { newSelected = [...selected.slice(1), value] } else { newSelected = [...selected, value] } } } else { if (isSelected(value) && !mandatory) { newSelected = [] } else { newSelected = [value] } } onSelectedChange?.(newSelected) } return ( <div ref={ref} className={cn('flex flex-wrap gap-2', column && 'flex-col', filter && 'flex-wrap', className)} data-chip-group="true" data-multiple={multiple || undefined} data-filter={filter || undefined} > {children?.({ selected, multiple, filter, isSelected, toggle })} </div> ) }, ) ChipGroup.displayName = 'ChipGroup' export { Chip, ChipGroup } -
components/ui/chip/chip.variants.ts 1.6 kB
import type { VariantProps } from 'class-variance-authority' import { cva } from 'class-variance-authority' /** * Variant definitions live in their own file (rather than the package * `index.ts`) so consuming Vue SFCs can import without creating a circular * dependency through the index. See card.variants.ts for the canonical * example + the SSR symptom that motivated the split. */ export const chipVariants = cva( 'inline-flex items-center justify-center gap-1 rounded-full text-xs font-medium w-fit whitespace-nowrap shrink-0 transition-colors duration-200 overflow-hidden focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2', { variants: { variant: { default: 'bg-muted text-muted-foreground hover:bg-muted/80', filled: 'bg-primary text-primary-foreground hover:bg-primary/90', outlined: 'border border-current bg-transparent hover:bg-accent', elevated: 'bg-primary/10 text-primary shadow-sm hover:bg-primary/20', success: 'bg-[var(--success)]/10 text-[var(--success)] dark:text-[var(--success)] hover:bg-[var(--success)]/20', warning: 'bg-[var(--warning)]/10 text-[var(--warning)] dark:text-[var(--warning)] hover:bg-[var(--warning)]/20', destructive: 'bg-destructive/10 text-destructive dark:text-destructive hover:bg-destructive/20', }, size: { sm: 'h-6 px-2 text-xs', default: 'h-7 px-2.5 text-xs', lg: 'h-8 px-3 text-sm', }, }, defaultVariants: { variant: 'default', size: 'default', }, }, ) export type ChipVariants = VariantProps<typeof chipVariants> -
components/ui/chip/index.ts 0.2 kB
export { Chip, ChipGroup, type ChipProps, type ChipGroupProps, type ChipGroupRenderProps } from './chip' export { chipVariants, type ChipVariants } from './chip.variants'
Raw manifest: https://react.uipkge.dev/r/react/chip.json