{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "chip",
  "type": "registry:component",
  "title": "Chip",
  "description": "A pill that can be pressed: a filter turned on and off, or an added value with a × to take it out.",
  "dependencies": [
    "@base-ui/react",
    "tailwind-variants"
  ],
  "registryDependencies": [],
  "cssVars": {
    "light": {
      "success": "oklch(0.696 0.17 162.48)",
      "warning": "oklch(0.769 0.188 70.08)",
      "info": "oklch(0.623 0.214 259.815)"
    },
    "dark": {
      "success": "oklch(0.696 0.17 162.48)",
      "warning": "oklch(0.769 0.188 70.08)",
      "info": "oklch(0.623 0.214 259.815)"
    }
  },
  "files": [
    {
      "path": "components/panelui/chip.tsx",
      "type": "registry:component",
      "target": "@components/panelui/chip.tsx",
      "content": "'use client';\n\n/**\n * Chip — a small pill that can be pressed: a filter turned on and off, or a value taken back out.\n *\n * ```tsx\n * <Chip.Group defaultValue={['open']} aria-label=\"Show\">\n *   <Chip value=\"open\">Open</Chip>\n *   <Chip value=\"merged\">Merged</Chip>\n *   <Chip value=\"closed\">Closed</Chip>\n * </Chip.Group>\n *\n * <Chip onRemove={() => drop('design')}>design</Chip>\n * ```\n *\n * ## Two jobs, one shape\n *\n * A chip on its own, or in a `Chip.Group`, is a toggle: pressing it turns a\n * filter on, and a tick slides in at its start while the pill fills, so a\n * row of them reads as a row of switches rather than a row of tags. The\n * group holds the values that are on as one array; pass `multiple={false}`\n * for a row where only one can be on.\n *\n * Given `onRemove`, a chip is a value that has been added — a recipient, a\n * tag — and carries a small × to take it back out. It is not a toggle then,\n * and pressing Backspace or Delete while its × has focus removes it too.\n *\n * For a label that only says what something is, and is never pressed, use\n * Badge.\n */\nimport { Toggle as BaseToggle } from '@base-ui/react/toggle';\nimport { ToggleGroup as BaseToggleGroup } from '@base-ui/react/toggle-group';\nimport type { ComponentProps, CSSProperties, KeyboardEvent, ReactNode } from 'react';\nimport { tv } from 'tailwind-variants';\n\nexport type ChipSize = 'sm' | 'md' | 'lg';\nexport type ChipColor = 'primary' | 'success' | 'info' | 'warning' | 'destructive';\n\nconst chipVariants = tv({\n  slots: {\n    root: [\n      'group/chip inline-flex shrink-0 items-center whitespace-nowrap rounded-full border font-medium outline-none select-none',\n      'border-border bg-background text-foreground shadow-xs dark:bg-input/30',\n      'transition-[background-color,border-color,color,padding] duration-200',\n      'focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background',\n      'data-disabled:pointer-events-none data-disabled:opacity-50',\n      '[&_svg:not([class*=size-])]:size-3.5 [&_svg]:shrink-0',\n    ],\n    // A toggle: tinted in its colour when on.\n    toggle: [\n      'cursor-pointer hover:bg-muted/60',\n      'data-pressed:border-[color-mix(in_oklab,var(--chip-color)_40%,var(--background))]',\n      'data-pressed:bg-[color-mix(in_oklab,var(--chip-color)_12%,var(--background))] dark:data-pressed:bg-[color-mix(in_oklab,var(--chip-color)_20%,var(--background))]',\n      'data-pressed:text-[color-mix(in_oklab,var(--chip-color),var(--foreground)_35%)]',\n    ],\n    // The tick's box opens from nothing, so the label slides over to make room for it.\n    check: [\n      'grid w-0 overflow-hidden opacity-0 transition-[width,opacity,margin] duration-200 ease-out',\n      'group-data-pressed/chip:w-3.5 group-data-pressed/chip:opacity-100 group-data-pressed/chip:me-1',\n      'motion-reduce:transition-none',\n    ],\n    remove: [\n      'relative -me-1 ms-1 inline-flex size-4 cursor-pointer items-center justify-center rounded-full text-muted-foreground outline-none',\n      'hover:bg-foreground/10 hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring',\n      // A bigger target than the mark.\n      \"after:absolute after:-inset-1.5 after:content-['']\",\n    ],\n    group: 'flex flex-wrap gap-2',\n  },\n  variants: {\n    size: {\n      sm: { root: 'h-6 px-2 text-xs' },\n      md: { root: 'h-7 px-2.5 text-[0.8125rem]' },\n      lg: { root: 'h-8 px-3 text-sm' },\n    },\n    color: {\n      primary: { root: '[--chip-color:var(--primary)]' },\n      success: { root: '[--chip-color:var(--success)]' },\n      info: { root: '[--chip-color:var(--info)]' },\n      warning: { root: '[--chip-color:var(--warning)]' },\n      destructive: { root: '[--chip-color:var(--destructive)]' },\n    },\n  },\n  defaultVariants: { size: 'md', color: 'primary' },\n});\n\ninterface ChipBaseProps {\n  /** Default `md`. */\n  size?: ChipSize;\n  /** The colour it takes when on. `primary` by default. */\n  color?: ChipColor;\n  className?: string;\n  style?: CSSProperties;\n  children?: ReactNode;\n}\n\nexport interface ChipToggleProps extends ChipBaseProps, Omit<BaseToggle.Props, 'className' | 'color' | 'children' | 'style'> {\n  onRemove?: undefined;\n}\n\nexport interface ChipRemovableProps extends ChipBaseProps, Omit<ComponentProps<'span'>, 'color' | 'children'> {\n  /**\n   * Makes the chip a value that can be taken out: it shows a × that calls\n   * this. A removable chip is not a toggle.\n   */\n  onRemove: () => void;\n  /** What the × is called to a screen reader. Default `Remove <text>`, when the text is a string. */\n  removeLabel?: string;\n  disabled?: boolean;\n}\n\nexport type ChipProps = ChipToggleProps | ChipRemovableProps;\n\n/**\n * A toggle pill. Takes `pressed`/`onPressedChange` or `defaultPressed` on its\n * own, and `value` inside a `Chip.Group`. Given `onRemove`, a removable value instead.\n */\nfunction ChipRoot(props: ChipProps) {\n  if (props.onRemove) {\n    const { size = 'md', color, className, children, onRemove, removeLabel, disabled, ...rest } = props;\n    const slots = chipVariants({ size, color });\n    const label = removeLabel ?? (typeof children === 'string' ? `Remove ${children}` : 'Remove');\n    const onKeyDown = (event: KeyboardEvent<HTMLButtonElement>) => {\n      if (event.key === 'Backspace' || event.key === 'Delete') {\n        event.preventDefault();\n        onRemove();\n      }\n    };\n    return (\n      <span\n        data-slot=\"chip\"\n        data-removable=\"\"\n        data-disabled={disabled ? '' : undefined}\n        className={slots.root({ className })}\n        {...rest}\n      >\n        {children}\n        <button\n          type=\"button\"\n          data-slot=\"chip-remove\"\n          aria-label={label}\n          disabled={disabled}\n          onClick={onRemove}\n          onKeyDown={onKeyDown}\n          className={slots.remove()}\n        >\n          <svg viewBox=\"0 0 16 16\" aria-hidden=\"true\" fill=\"none\" className=\"size-3\">\n            <path d=\"M4.5 4.5l7 7m0-7l-7 7\" stroke=\"currentColor\" strokeWidth={1.75} strokeLinecap=\"round\" />\n          </svg>\n        </button>\n      </span>\n    );\n  }\n\n  const { size = 'md', color, className, children, onRemove: _onRemove, ...rest } = props;\n  const slots = chipVariants({ size, color });\n  return (\n    <BaseToggle data-slot=\"chip\" data-size={size} className={slots.root({ className: [slots.toggle(), className] })} {...rest}>\n      <span data-slot=\"chip-check\" aria-hidden=\"true\" className={slots.check()}>\n        <svg viewBox=\"0 0 16 16\" fill=\"none\" className=\"size-3.5\">\n          <path d=\"M3.5 8.5 6.6 11.5 12.5 4.75\" stroke=\"currentColor\" strokeWidth={2} strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n        </svg>\n      </span>\n      {children}\n    </BaseToggle>\n  );\n}\nChipRoot.displayName = 'Chip';\n\nexport interface ChipGroupProps extends Omit<BaseToggleGroup.Props<string>, 'className'> {\n  className?: string;\n}\n\n/**\n * A row of toggle chips whose values are held as one array. Several can be on\n * at once; pass `multiple={false}` for one at a time.\n */\nfunction ChipGroup({ multiple = true, className, ...props }: ChipGroupProps) {\n  return (\n    <BaseToggleGroup\n      data-slot=\"chip-group\"\n      multiple={multiple}\n      className={chipVariants().group({ className })}\n      {...props}\n    />\n  );\n}\nChipGroup.displayName = 'Chip.Group';\n\nexport const Chip = Object.assign(ChipRoot, { Group: ChipGroup });\n\nexport { ChipGroup };\n"
    }
  ]
}
