{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "accordion",
  "title": "Accordion",
  "description": "Stacked disclosure sections with numbered, dashed and separated styles.",
  "dependencies": [
    "lucide-react",
    "radix-ui"
  ],
  "registryDependencies": [
    "utils",
    "https://ui.cuelark.com/r/theme.json",
    "https://ui.cuelark.com/r/motion.json"
  ],
  "files": [
    {
      "path": "src/registry/cuelark/ui/accordion.tsx",
      "content": "\"use client\";\n\nimport * as React from \"react\";\nimport { Accordion as AccordionPrimitive } from \"radix-ui\";\nimport { PlusIcon } from \"lucide-react\";\n\nimport { enterChildren, motionScale } from \"@/lib/motion\";\nimport { cn } from \"@/lib/utils\";\n\n/** Lets content skip its reveal for items that are already open on first render. */\nconst HydratedContext = React.createContext<React.RefObject<boolean> | null>(null);\n\ntype AccordionVariant = \"lined\" | \"dashed\" | \"separated\";\n\ntype AccordionProps = React.ComponentProps<typeof AccordionPrimitive.Root> & {\n  variant?: AccordionVariant;\n  /** Prefixes each trigger with a mono index (01, 02, …) using CSS counters, so it stays correct with any item order. */\n  numbered?: boolean;\n};\n\nfunction Accordion({ className, variant = \"lined\", numbered = false, ...props }: AccordionProps) {\n  const hydrated = React.useRef(false);\n  React.useEffect(() => {\n    hydrated.current = true;\n  }, []);\n  return (\n    <HydratedContext.Provider value={hydrated}>\n      <AccordionPrimitive.Root\n        data-slot=\"accordion\"\n        data-variant={variant}\n        data-numbered={numbered ? \"\" : undefined}\n        className={cn(\"w-full [counter-reset:cue-accordion]\", variant === \"separated\" && \"flex flex-col gap-2\", className)}\n        {...props}\n      />\n    </HydratedContext.Provider>\n  );\n}\n\nfunction AccordionItem({ className, ...props }: React.ComponentProps<typeof AccordionPrimitive.Item>) {\n  return (\n    <AccordionPrimitive.Item\n      data-slot=\"accordion-item\"\n      className={cn(\n        \"[counter-increment:cue-accordion]\",\n        \"[[data-variant=lined]>&]:border-b [[data-variant=lined]>&]:border-border [[data-variant=lined]>&]:last:border-b-0\",\n        \"[[data-variant=dashed]>&]:cue-dash-b [[data-variant=dashed]>&]:last:bg-none\",\n        \"[[data-variant=separated]>&]:rounded-lg [[data-variant=separated]>&]:border [[data-variant=separated]>&]:border-border [[data-variant=separated]>&]:bg-card [[data-variant=separated]>&]:px-4 [[data-variant=separated]>&]:shadow-control [[data-variant=separated]>&]:transition-shadow [[data-variant=separated]>&]:data-[state=open]:shadow-raised\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\n/** Renders inside a real heading (`<h3>`) so FAQ content keeps its document outline. */\nfunction AccordionTrigger({ className, children, ...props }: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {\n  return (\n    <AccordionPrimitive.Header className=\"flex\">\n      <AccordionPrimitive.Trigger\n        data-slot=\"accordion-trigger\"\n        className={cn(\n          \"group/trigger flex flex-1 items-start gap-3 rounded-md py-4 text-left text-[0.9375rem] font-medium outline-none transition-colors hover:underline hover:underline-offset-4 focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50\",\n          \"[[data-numbered]_&]:before:w-6 [[data-numbered]_&]:before:shrink-0 [[data-numbered]_&]:before:pt-0.5 [[data-numbered]_&]:before:font-mono [[data-numbered]_&]:before:text-xs [[data-numbered]_&]:before:text-muted-foreground [[data-numbered]_&]:before:tabular-nums [[data-numbered]_&]:before:content-[counter(cue-accordion,decimal-leading-zero)]\",\n          className,\n        )}\n        {...props}\n      >\n        <span className=\"flex-1\">{children}</span>\n        <PlusIcon\n          aria-hidden=\"true\"\n          className=\"mt-0.5 size-4 shrink-0 text-muted-foreground transition-transform duration-200 ease-cue group-hover/trigger:text-foreground group-data-[state=open]/trigger:rotate-45 motion-reduce:transition-none\"\n        />\n      </AccordionPrimitive.Trigger>\n    </AccordionPrimitive.Header>\n  );\n}\n\n/** While the panel opens, its children rise in one after another (GSAP stagger). */\nfunction AccordionContent({ className, children, ...props }: React.ComponentProps<typeof AccordionPrimitive.Content>) {\n  const hydrated = React.useContext(HydratedContext);\n  const reveal = React.useCallback(\n    (node: HTMLDivElement | null) => {\n      if (!node || !hydrated?.current || node.dataset.entered !== undefined) return;\n      node.dataset.entered = \"\";\n      const scale = motionScale(node);\n      if (!scale) return;\n      const targets = node.children.length ? node.children : node;\n      enterChildren(targets instanceof Element ? [targets] : targets, { opacity: 0, y: 8 * scale }, { stagger: 0.05, delay: 0.05 });\n    },\n    [hydrated],\n  );\n  return (\n    <AccordionPrimitive.Content\n      data-slot=\"accordion-content\"\n      className=\"overflow-hidden text-sm text-muted-foreground data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down\"\n      {...props}\n    >\n      <div ref={reveal} className={cn(\"pe-7 pb-4 [[data-numbered]_&]:ps-9\", className)}>\n        {children}\n      </div>\n    </AccordionPrimitive.Content>\n  );\n}\n\nexport { Accordion, AccordionItem, AccordionTrigger, AccordionContent };\nexport type { AccordionProps, AccordionVariant };\n",
      "type": "registry:ui"
    }
  ],
  "docs": "Docs and examples: https://ui.cuelark.com/components/accordion",
  "categories": [
    "layout"
  ],
  "type": "registry:ui"
}