{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "accordion",
  "title": "Accordion",
  "description": "A list of disclosures built on native details elements.",
  "dependencies": [
    "lucide-react@^1.31.0"
  ],
  "registryDependencies": [
    "utils"
  ],
  "files": [
    {
      "path": "registry/default/accordion/accordion.tsx",
      "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { Plus } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport type AccordionItem = {\n  id: string\n  title: React.ReactNode\n  content: React.ReactNode\n}\n\nexport type AccordionProps = Omit<\n  React.HTMLAttributes<HTMLDivElement>,\n  \"children\" | \"defaultValue\"\n> & {\n  items: readonly AccordionItem[]\n  /** Only one panel stays open at a time. Defaults to true. */\n  exclusive?: boolean\n  /** Ids open on first render. */\n  defaultOpen?: readonly string[]\n  icon?: React.ReactNode\n  onToggle?: (id: string, open: boolean) => void\n  /**\n   * Classes for the parts inside. The shape here is a sensible default, not a\n   * design: a disclosure list belongs to the page it sits on.\n   */\n  classNames?: {\n    item?: string\n    trigger?: string\n    marker?: string\n    content?: string\n  }\n}\n\n/**\n * Built on native disclosure elements, so the open and closed state, keyboard\n * handling, and find-in-page expansion come from the browser rather than from\n * scripted state. Exclusivity uses the shared name attribute for the same\n * reason.\n */\nexport function Accordion({\n  items,\n  exclusive = true,\n  defaultOpen,\n  icon,\n  onToggle,\n  classNames,\n  className,\n  ...rootProps\n}: AccordionProps) {\n  const groupName = React.useId()\n  const open = React.useMemo(() => new Set(defaultOpen ?? []), [defaultOpen])\n\n  return (\n    <div\n      data-slot=\"accordion\"\n      className={cn(\n        \"border-border divide-border min-w-0 divide-y overflow-hidden rounded-[calc(var(--radius)+0.15rem)] border\",\n        className\n      )}\n      {...rootProps}\n    >\n      {items.map((item) => (\n        <details\n          key={item.id}\n          data-slot=\"accordion-item\"\n          name={exclusive ? groupName : undefined}\n          open={open.has(item.id) || undefined}\n          className={cn(\"group bg-card/40 open:bg-card\", classNames?.item)}\n          onToggle={(event) =>\n            onToggle?.(\n              item.id,\n              (event.currentTarget as HTMLDetailsElement).open\n            )\n          }\n        >\n          <summary\n            data-slot=\"accordion-trigger\"\n            className={cn(\n              \"text-foreground hover:bg-muted/60 flex min-h-11 cursor-pointer list-none items-center gap-3 px-4 py-3 text-sm transition-colors duration-150 outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:ring-inset motion-reduce:transition-none [&::-webkit-details-marker]:hidden\",\n              classNames?.trigger\n            )}\n          >\n            <span className=\"min-w-0 flex-1\">{item.title}</span>\n            <span\n              aria-hidden=\"true\"\n              className={cn(\n                \"text-muted-foreground shrink-0 transition-transform duration-200 group-open:rotate-45 motion-reduce:transition-none\",\n                classNames?.marker\n              )}\n            >\n              {icon ?? <Plus size={18} strokeWidth={1.8} />}\n            </span>\n          </summary>\n\n          <div\n            data-slot=\"accordion-content\"\n            className={cn(\n              \"text-muted-foreground px-4 pb-4 text-sm leading-relaxed\",\n              classNames?.content\n            )}\n          >\n            {item.content}\n          </div>\n        </details>\n      ))}\n    </div>\n  )\n}\n",
      "type": "registry:ui"
    }
  ],
  "categories": [
    "disclosure",
    "faq",
    "control"
  ],
  "type": "registry:ui"
}