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