{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "accordion",
  "title": "Accordion",
  "description": "A accordion component.",
  "dependencies": [
    "@hugeicons/react",
    "@hugeicons/core-free-icons"
  ],
  "files": [
    {
      "path": "registry/default/accordion/accordion.tsx",
      "content": "import * as React from \"react\";\nimport { Accordion as BaseAccordion } from \"@base-ui/react/accordion\";\nimport { cn } from \"@/lib/utils\";\n\nimport { HugeiconsIcon } from \"@hugeicons/react\";\nimport ArrowDown01Icon from \"@hugeicons/core-free-icons/ArrowDown01Icon\";\ntype AccordionVariant =\n  | \"default\"\n  | \"split\"\n  | \"outline\"\n  | \"nested\"\n  | \"isolated-bordered\"\n  | \"isolated-filled\"\n  | \"isolated-filled-bordered\";\n\nfunction Accordion({\n  className,\n  multiple = false,\n  variant = \"default\",\n  ...props\n}: BaseAccordion.Root.Props & { variant?: AccordionVariant }) {\n  return (\n    <BaseAccordion.Root\n      data-slot=\"accordion\"\n      data-variant={variant}\n      multiple={multiple}\n      className={cn(\n        \"group flex w-full flex-col\",\n        variant === \"split\" && \"space-y-2\",\n        variant === \"outline\" && \"bg-card overflow-hidden rounded-lg border\",\n        variant === \"nested\" && \"bg-muted rounded-lg border p-1\",\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction AccordionItem({ className, ...props }: BaseAccordion.Item.Props) {\n  return (\n    <BaseAccordion.Item\n      data-slot=\"accordion-item\"\n      className={cn(\n        \"ease-out-expo transition-[margin,border-radius,border] duration-250\",\n        // Default variant styles\n        \"group-data-[variant=default]:border-b group-data-[variant=default]:last:border-b-0\",\n        // Split variant styles (individual cards)\n        \"group-data-[variant=split]:bg-card group-data-[variant=split]:border-border group-data-[variant=split]:overflow-hidden group-data-[variant=split]:rounded-lg group-data-[variant=split]:border\",\n        // Outline variant styles (items within single card)\n        \"group-data-[variant=outline]:border-border group-data-[variant=outline]:border-b group-data-[variant=outline]:last:border-b-0\",\n        // Nested variant styles - items within the single outer card\n        \"group-data-[variant=nested]:mt-0.5 group-data-[variant=nested]:first:mt-0\",\n        // Isolated bordered variant styles - dynamically separates open items from closed ones\n        // Base styles: all items have borders and background to look like cards\n        \"group-data-[variant=isolated-bordered]:bg-card group-data-[variant=isolated-bordered]:border-border group-data-[variant=isolated-bordered]:overflow-hidden group-data-[variant=isolated-bordered]:border\",\n        // Closed items: group together by overlapping borders with negative margin\n        // Only apply to closed items that follow another closed item (not open items, first item, or items after open items)\n        \"group-data-[variant=isolated-bordered]:relative group-data-[variant=isolated-bordered]:not-first:not-data-open:not-[[data-open]+&]:-mt-px\",\n        // Opened item - separated with margins\n        \"group-data-[variant=isolated-bordered]:data-open:mt-2 group-data-[variant=isolated-bordered]:data-open:mb-2 group-data-[variant=isolated-bordered]:data-open:rounded-lg\",\n        // First item\n        \"group-data-[variant=isolated-bordered]:first:rounded-t-lg group-data-[variant=isolated-bordered]:data-open:first:mt-0\",\n        // Last item\n        \"group-data-[variant=isolated-bordered]:last:rounded-b-lg group-data-[variant=isolated-bordered]:data-open:last:mb-0\",\n        // Item after open item: round top corners (start of new group)\n        \"group-data-[variant=isolated-bordered]:[[data-open]+&]:rounded-t-lg\",\n        // Item before open item: round bottom corners (end of group)\n        \"group-data-[variant=isolated-bordered]:[&:has(+_[data-open])]:rounded-b-lg\",\n        // Isolated filled variant\n        \"group-data-[variant=isolated-filled]:bg-muted group-data-[variant=isolated-filled]:overflow-hidden\",\n        // Opened item - separated with margins and rounded\n        \"group-data-[variant=isolated-filled]:data-open:my-2 group-data-[variant=isolated-filled]:data-open:rounded-lg\",\n        // First item\n        \"group-data-[variant=isolated-filled]:first:rounded-t-lg group-data-[variant=isolated-filled]:data-open:first:mt-0\",\n        // Last item\n        \"group-data-[variant=isolated-filled]:last:rounded-b-lg group-data-[variant=isolated-filled]:data-open:last:mb-0\",\n        // Item after open item: round top corners (start of new group)\n        \"group-data-[variant=isolated-filled]:[[data-open]+&]:rounded-t-lg\",\n        // Item before open item: round bottom corners (end of group)\n        \"group-data-[variant=isolated-filled]:[&:has(+_[data-open])]:rounded-b-lg\",\n        // Isolated filled bordered variant - filled background with borders between closed items\n        \"group-data-[variant=isolated-filled-bordered]:bg-muted group-data-[variant=isolated-filled-bordered]:overflow-hidden\",\n        // All items except last have border-bottom to prevent layout shift, default to visible border\n        \"group-data-[variant=isolated-filled-bordered]:not-last:border-border group-data-[variant=isolated-filled-bordered]:not-last:border-b\",\n        // Make border transparent (invisible) for: items before open items, and open items themselves\n        \"group-data-[variant=isolated-filled-bordered]:[&:has(+_[data-open])]:border-transparent\",\n        \"group-data-[variant=isolated-filled-bordered]:data-open:border-transparent\",\n        // Opened item - separated with margins and rounded\n        \"group-data-[variant=isolated-filled-bordered]:data-open:my-2 group-data-[variant=isolated-filled-bordered]:data-open:rounded-lg\",\n        // First item\n        \"group-data-[variant=isolated-filled-bordered]:first:rounded-t-lg group-data-[variant=isolated-filled-bordered]:data-open:first:mt-0\",\n        // Last item\n        \"group-data-[variant=isolated-filled-bordered]:last:rounded-b-lg group-data-[variant=isolated-filled-bordered]:data-open:last:mb-0\",\n        // Item after open item: round top corners (start of new group)\n        \"group-data-[variant=isolated-filled-bordered]:[[data-open]+&]:rounded-t-lg\",\n        // Item before open item: round bottom corners (end of group)\n        \"group-data-[variant=isolated-filled-bordered]:[&:has(+_[data-open])]:rounded-b-lg\",\n\n        className,\n      )}\n      {...props}\n    />\n  );\n}\n\nfunction AccordionHeader({ className, ...props }: BaseAccordion.Header.Props) {\n  return (\n    <BaseAccordion.Header\n      data-slot=\"accordion-header\"\n      // `not-prose` guards the trigger from document typography when the\n      // accordion is rendered inside a prose/markdown container (e.g. MDX docs),\n      // which would otherwise style this heading with large margins and an\n      // inflated line-height. Inert outside a prose context.\n      className={cn(\"not-prose\", className)}\n      {...props}\n    />\n  );\n}\n\ninterface AccordionTriggerProps extends BaseAccordion.Trigger.Props {\n  showIndicator?: boolean;\n  indicatorType?: \"chevron\" | \"plus\";\n  indicatorPosition?: \"start\" | \"end\";\n  icon?: React.ReactNode;\n  subtitle?: React.ReactNode;\n}\n\nfunction AccordionTrigger({\n  children,\n  className,\n  showIndicator = true,\n  indicatorType = \"plus\",\n  indicatorPosition = \"end\",\n  icon,\n  subtitle,\n  ...props\n}: AccordionTriggerProps) {\n  const hasStartIndicator = showIndicator && indicatorPosition === \"start\";\n  const hasEndIndicator = showIndicator && indicatorPosition === \"end\";\n\n  const renderIndicator = () => {\n    if (!showIndicator) return null;\n\n    const indicatorIcon =\n      indicatorType === \"chevron\" ? (\n        <HugeiconsIcon\n          icon={ArrowDown01Icon}\n          data-slot=\"accordion-indicator\"\n          className=\"text-muted-foreground ease-out-expo size-4 shrink-0 transition-transform duration-200\"\n          strokeWidth={2}\n        />\n      ) : (\n        <PlusIcon\n          data-slot=\"accordion-indicator\"\n          className=\"text-muted-foreground ease-out-expo size-4 shrink-0 transition-transform duration-200\"\n        />\n      );\n\n    return (\n      <span className=\"text-muted-foreground shrink-0\" aria-hidden=\"true\">\n        {indicatorIcon}\n      </span>\n    );\n  };\n\n  return (\n    <AccordionHeader>\n      <BaseAccordion.Trigger\n        data-slot=\"accordion-trigger\"\n        data-has-icon={hasStartIndicator ? \"true\" : undefined}\n        className={cn(\n          \"group/trigger flex w-full cursor-pointer items-center justify-between gap-3 p-3.5 text-left text-sm font-medium outline-none disabled:pointer-events-none disabled:opacity-60\",\n          // Default variant styles\n          \"group-data-[variant=default]:px-0\",\n          // Split variant styles\n          \"group-data-[variant=split]:rounded-t-lg\",\n          // Nested variant styles - trigger with subtle interaction\n          \"group-data-[variant=nested]:hover:bg-background group-data-[variant=nested]:dark:hover:bg-background/50 group-data-[variant=nested]:rounded-sm group-data-[variant=nested]:px-3 group-data-[variant=nested]:py-2.5\",\n          // Indicator rotation animations\n          indicatorType === \"chevron\" &&\n            \"[&[data-panel-open]_[data-slot=accordion-indicator]]:rotate-180\",\n          indicatorType === \"plus\" &&\n            \"[&[data-panel-open]_[data-slot=accordion-indicator]]:rotate-90\",\n          className,\n        )}\n        {...props}\n      >\n        {hasStartIndicator && renderIndicator()}\n\n        {/* icon prop — only rendered when indicator is at end position */}\n        {icon && !hasStartIndicator && (\n          <span className=\"text-muted-foreground shrink-0\" aria-hidden=\"true\">\n            {icon}\n          </span>\n        )}\n\n        <div className=\"flex min-w-0 flex-1 flex-col gap-0.5\">\n          <span className=\"underline-offset-2 group-hover/trigger:underline\">\n            {children}\n          </span>\n          {subtitle && (\n            <span className=\"text-muted-foreground text-sm no-underline\">\n              {subtitle}\n            </span>\n          )}\n        </div>\n\n        {hasEndIndicator && renderIndicator()}\n      </BaseAccordion.Trigger>\n    </AccordionHeader>\n  );\n}\n\nfunction AccordionContent({\n  children,\n  className,\n  ...props\n}: BaseAccordion.Panel.Props) {\n  return (\n    <BaseAccordion.Panel\n      data-slot=\"accordion-content\"\n      className={cn(\n        \"ease-out-expo h-(--accordion-panel-height) overflow-hidden text-sm transition-[height,opacity] duration-250 data-ending-style:h-0 data-ending-style:opacity-0 data-starting-style:h-0 data-starting-style:opacity-0\",\n      )}\n      {...props}\n    >\n      <div\n        className={cn(\n          \"text-muted-foreground p-3.5\",\n          \"group-data-[variant=default]:px-0 group-data-[variant=default]:pt-0\",\n          \"group-data-[variant=split]:pt-0\",\n          \"group-data-[variant=outline]:pt-0\",\n          // Nested variant\n          \"group-data-[variant=nested]:bg-background group-data-[variant=nested]:mt-1 group-data-[variant=nested]:mb-0.5 group-data-[variant=nested]:rounded-sm group-data-[variant=nested]:border group-data-[variant=nested]:p-3 group-data-[variant=nested]:[[data-slot=accordion-item]:last-child_&]:mb-0\",\n          // Isolated bordered variant\n          \"group-data-[variant=isolated-bordered]:pt-0\",\n          // Isolated filled variant\n          \"group-data-[variant=isolated-filled]:pt-0\",\n          // Isolated filled bordered variant\n          \"group-data-[variant=isolated-filled-bordered]:pt-0\",\n          // Icon alignment - add left padding when parent item contains a trigger with icon\n          \"[[data-slot=accordion-item]:has([data-has-icon])_&]:pl-[calc(1rem+0.75rem)]\",\n          \"[[data-slot=accordion-item]:has([data-has-icon])_&]:group-data-[variant=default]:pl-[calc(1rem+0.75rem)]\",\n          className,\n        )}\n      >\n        {children}\n      </div>\n    </BaseAccordion.Panel>\n  );\n}\n\nexport {\n  Accordion,\n  AccordionItem,\n  AccordionHeader,\n  AccordionTrigger,\n  AccordionContent,\n};\n\nfunction PlusIcon(props: React.ComponentProps<\"svg\">) {\n  return (\n    <svg viewBox=\"0 0 24 24\" fill=\"none\" {...props}>\n      {/* Horizontal bar - fades out when accordion opens */}\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M2.75 12C2.75 11.3096 3.30964 10.75 4 10.75H20C20.6904 10.75 21.25 11.3096 21.25 12C21.25 12.6904 20.6904 13.25 20 13.25H4C3.30964 13.25 2.75 12.6904 2.75 12Z\"\n        fill=\"currentColor\"\n        className=\"ease-out-expo transition-opacity duration-200 in-data-panel-open:opacity-0\"\n      />\n      {/* Vertical bar - remains visible (becomes horizontal after 90° rotation) */}\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M12 2.75C12.6904 2.75 13.25 3.30964 13.25 4V20C13.25 20.6904 12.6904 21.25 12 21.25C11.3096 21.25 10.75 20.6904 10.75 20V4C10.75 3.30964 11.3096 2.75 12 2.75Z\"\n        fill=\"currentColor\"\n      />\n    </svg>\n  );\n}\n",
      "type": "registry:ui",
      "target": "components/ui/cubby-ui/accordion.tsx"
    }
  ],
  "type": "registry:ui"
}