{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "accordion",
  "type": "registry:ui",
  "title": "Accordion",
  "description": "Accessible collapsible content sections with tactile pastel headers.",
  "dependencies": [
    "clsx",
    "tailwind-merge",
    "lucide-react"
  ],
  "devDependencies": [],
  "registryDependencies": [],
  "files": [
    {
      "path": "components/ui/accordion.tsx",
      "content": "'use client'\n\nimport * as React from 'react'\nimport { ChevronDown, Plus, Minus } from 'lucide-react'\nimport { cn } from '@/lib/utils'\n\n/* ------------------------------------------------------------------ */\n/* Compound API                                                        */\n/* ------------------------------------------------------------------ */\n\nexport interface AccordionItemProps {\n  id: string\n  title: React.ReactNode\n  content: React.ReactNode\n  disabled?: boolean\n  open?: boolean\n  onToggle?: (id: string) => void\n  variant?: 'default' | 'yellow' | 'numbered' | 'plus-minus'\n  showNumbers?: boolean\n  number?: string\n}\n\nexport function AccordionItem({\n  id,\n  title,\n  content,\n  disabled,\n  open = false,\n  onToggle,\n  variant = 'default',\n  showNumbers = false,\n  number,\n}: AccordionItemProps) {\n  const isNumbered = showNumbers || variant === 'numbered'\n  const isPlusMinus = variant === 'plus-minus' || variant === 'numbered'\n  const contentId = `accordion-content-${id}`\n  const titleId = `accordion-title-${id}`\n  const heightRef = React.useRef<HTMLDivElement>(null)\n\n  return (\n    <div\n      className={cn(\n        'overflow-hidden rounded-[20px] border-3 border-rk-ink transition-all',\n        open ? 'bg-rk-primary rk-shadow-md' : 'bg-rk-surface rk-shadow-sm hover:rk-shadow-md'\n      )}\n    >\n      <h3>\n        <button\n          type=\"button\"\n          aria-expanded={open}\n          aria-controls={contentId}\n          id={titleId}\n          disabled={disabled}\n          onClick={() => onToggle?.(id)}\n          className={cn(\n            'flex min-h-14 w-full items-center justify-between gap-4 px-5 py-4 text-left font-display text-base font-black text-rk-ink transition-colors focus:outline-none disabled:cursor-not-allowed disabled:opacity-50 cursor-pointer'\n          )}\n        >\n          <span className=\"flex items-center gap-3\">\n            {isNumbered && (\n              <span className=\"font-mono text-xs font-black opacity-60\">\n                {number}\n              </span>\n            )}\n            <span>{title}</span>\n          </span>\n\n          {isPlusMinus ? (\n            open ? (\n              <Minus className=\"h-5 w-5 shrink-0 stroke-[3] text-rk-ink\" aria-hidden=\"true\" />\n            ) : (\n              <Plus className=\"h-5 w-5 shrink-0 stroke-[3] text-rk-ink\" aria-hidden=\"true\" />\n            )\n          ) : (\n            <ChevronDown\n              className={cn(\n                'h-5 w-5 shrink-0 stroke-[3] text-rk-ink transition-transform duration-200',\n                open && 'rotate-180'\n              )}\n              aria-hidden=\"true\"\n            />\n          )}\n        </button>\n      </h3>\n      <div\n        id={contentId}\n        role=\"region\"\n        aria-labelledby={titleId}\n        className={cn(\n          'grid transition-[grid-template-rows] duration-300 ease-out',\n          open ? 'grid-rows-[1fr]' : 'grid-rows-[0fr]'\n        )}\n      >\n        <div ref={heightRef} className=\"overflow-hidden\">\n          <div className=\"border-t-2 border-rk-ink/15 px-5 py-4 text-sm font-extrabold leading-relaxed text-rk-ink/80\">\n            {content}\n          </div>\n        </div>\n      </div>\n    </div>\n  )\n}\n\n/* ------------------------------------------------------------------ */\n/* Legacy API                                                          */\n/* ------------------------------------------------------------------ */\n\nexport interface AccordionItemConfig {\n  id: string\n  title: React.ReactNode\n  content: React.ReactNode\n  disabled?: boolean\n}\n\nexport interface AccordionProps {\n  items: AccordionItemConfig[]\n  type?: 'single' | 'multiple'\n  value?: string | string[]\n  defaultValue?: string | string[]\n  onValueChange?: (value: string | string[]) => void\n  collapsible?: boolean\n  showNumbers?: boolean\n  variant?: 'default' | 'yellow' | 'numbered' | 'plus-minus'\n  className?: string\n}\n\nexport function Accordion({\n  items,\n  type = 'single',\n  value: controlledValue,\n  defaultValue,\n  onValueChange,\n  collapsible = true,\n  showNumbers = false,\n  variant = 'default',\n  className,\n}: AccordionProps) {\n  const initialValue = defaultValue ?? (type === 'multiple' ? [] : '')\n  const [internalValue, setInternalValue] = React.useState<string | string[]>(initialValue)\n  const currentValue = controlledValue ?? internalValue\n  const openItems = Array.isArray(currentValue) ? currentValue : currentValue ? [currentValue] : []\n\n  const toggleItem = (id: string) => {\n    const isOpen = openItems.includes(id)\n    let nextValue: string | string[]\n\n    if (type === 'multiple') {\n      nextValue = isOpen ? openItems.filter((item) => item !== id) : [...openItems, id]\n    } else {\n      nextValue = isOpen && collapsible ? '' : id\n    }\n\n    setInternalValue(nextValue)\n    onValueChange?.(nextValue)\n  }\n\n  return (\n    <div className={cn('w-full space-y-3 font-sans', className)}>\n      {items.map((item, index) => (\n        <AccordionItem\n          key={item.id}\n          id={item.id}\n          title={item.title}\n          content={item.content}\n          disabled={item.disabled}\n          open={openItems.includes(item.id)}\n          onToggle={toggleItem}\n          variant={variant}\n          showNumbers={showNumbers}\n          number={String(index + 1).padStart(2, '0')}\n        />\n      ))}\n    </div>\n  )\n}\n",
      "type": "registry:ui",
      "target": "components/ui/accordion.tsx"
    }
  ]
}