{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "organic-button",
  "type": "registry:ui",
  "description": "Anchor-based CTA with fixed SVG end caps, shared surface colors via CSS variables, and size and animation variants",
  "dependencies": [
    "@radix-ui/react-slot",
    "class-variance-authority",
    "lucide-react"
  ],
  "files": [
    {
      "path": "registry/default/ui/organic-button.tsx",
      "content": "import { forwardRef, type AnchorHTMLAttributes, type ReactNode } from \"react\"\nimport { Slot } from \"@radix-ui/react-slot\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\nimport { ArrowUpRight } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\n/** Shared fill for all organic SVG paths — driven by `--organic-surface` on the button root. */\nconst fillOrganic = \"fill-[var(--organic-surface)]\"\n\nconst organicButtonVariants = cva(\"flex w-fit flex-col\", {\n  variants: {\n    variantColor: {\n      primary:\n        \"text-[var(--organic-fg)] [--organic-fg:theme(colors.white)] [--organic-surface:theme(colors.neutral.950)]\",\n      secondary:\n        \"text-[var(--organic-fg)] [--organic-fg:var(--secondary-foreground)] [--organic-surface:var(--secondary)]\",\n      /** Plum surface + cream label — matches dither hero (colors only; same motion as primary) */\n      dither:\n        \"text-[var(--organic-fg)] [--organic-fg:#f4f8e8] [--organic-surface:#301c2a]\",\n      /** Light surface for inactive toggle chips (quick toggles, etc.) */\n      toggleOff:\n        \"text-[var(--organic-fg)] [--organic-fg:#404040] [--organic-surface:#ffffff] dark:[--organic-fg:#a3a3a3] dark:[--organic-surface:#262626]\",\n    },\n    size: {\n      sm: \"h-9 min-h-9 [&_.organic-icon]:size-3.5 [&_.organic-label]:text-sm\",\n      md: \"h-11 min-h-11 [&_.organic-icon]:size-4 [&_.organic-label]:text-base\",\n      lg: \"h-14 min-h-14 [&_.organic-icon]:size-5 [&_.organic-label]:text-lg\",\n    },\n    animationSpeed: {\n      slow: \"[--organic-duration:500ms]\",\n      normal: \"[--organic-duration:400ms]\",\n      fast: \"[--organic-duration:300ms]\",\n    },\n  },\n  defaultVariants: {\n    size: \"md\",\n    variantColor: \"primary\",\n    animationSpeed: \"normal\",\n  },\n})\n\ninterface OrganicShapeButtonProps\n  extends AnchorHTMLAttributes<HTMLAnchorElement>,\n    VariantProps<typeof organicButtonVariants> {\n  asChild?: boolean\n  label: string\n  icon?: ReactNode\n  animationSpeed?: \"slow\" | \"normal\" | \"fast\"\n}\n\nconst svgShapeAttrs = {\n  preserveAspectRatio: \"xMidYMid meet\" as const,\n}\n\nfunction isExternalHref(href: string | undefined): boolean {\n  if (!href) {\n    return false\n  }\n  return (\n    href.startsWith(\"http://\") ||\n    href.startsWith(\"https://\") ||\n    href.startsWith(\"//\")\n  )\n}\n\nexport const OrganicButton = forwardRef<\n  HTMLAnchorElement,\n  OrganicShapeButtonProps\n>(\n  (\n    {\n      asChild,\n      label,\n      className,\n      icon = (\n        <ArrowUpRight className=\"organic-icon stroke-current transition-transform duration-100 group-hover/organic:rotate-45 group-hover/organic:scale-110\" />\n      ),\n      size = \"md\",\n      variantColor = \"primary\",\n      animationSpeed = \"normal\",\n      href,\n      target,\n      rel,\n      ...props\n    },\n    ref\n  ) => {\n    const Comp = asChild ? Slot : \"a\"\n\n    const minWBySize = {\n      sm: \"min-w-[9rem]\",\n      md: \"min-w-[10.5rem]\",\n      lg: \"min-w-[12rem]\",\n    } as const\n    const minW = minWBySize[size ?? \"md\"]\n\n    const resolvedTarget = target ?? (isExternalHref(href) ? \"_blank\" : \"_self\")\n    const resolvedRel =\n      rel ?? (isExternalHref(href) ? \"noopener noreferrer\" : undefined)\n\n    return (\n      <div\n        className={cn(\n          organicButtonVariants({\n            variantColor,\n            size,\n            animationSpeed,\n          })\n        )}\n      >\n        <Comp\n          className={cn(\n            \"group/organic inline-flex h-full min-h-0 w-full min-w-0 max-w-full focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background active:scale-[0.96] active:transition-transform disabled:cursor-not-allowed\",\n            minW,\n            className\n          )}\n          href={href}\n          ref={ref}\n          rel={resolvedRel}\n          target={resolvedTarget}\n          {...props}\n        >\n          <div className=\"flex h-full min-h-0 min-w-0 flex-1 flex-row items-stretch\">\n            <div className=\"flex h-full min-h-0 min-w-0 flex-1 items-stretch\">\n              <RoundedFlatRight />\n\n              <div\n                className={cn(\n                  \"flex h-full min-h-0 min-w-0 flex-1 items-center justify-start overflow-visible whitespace-nowrap bg-[var(--organic-surface)] pr-2 text-[var(--organic-fg)]\"\n                )}\n              >\n                <span className=\"flex items-center justify-start pl-2 transition-[padding] duration-[var(--organic-duration,400ms)] ease-in-out\">\n                  <span className=\"organic-label shrink-0 font-brand font-semibold leading-none\">\n                    {label}\n                  </span>\n                </span>\n              </div>\n\n              <DescendingWall />\n            </div>\n\n            <div className=\"-ml-px flex h-full min-h-0 w-max shrink-0 items-stretch\">\n              <AscendingWall />\n              <div\n                className={cn(\n                  \"flex h-full shrink-0 items-center justify-center overflow-visible whitespace-nowrap bg-[var(--organic-surface)] text-[var(--organic-fg)]\"\n                )}\n              >\n                <span className=\"flex items-center px-0 transition-[padding] duration-[var(--organic-duration,400ms)] ease-in-out group-hover/organic:px-2\">\n                  {icon}\n                </span>\n              </div>\n\n              <FlatRoundedRight />\n            </div>\n          </div>\n        </Comp>\n      </div>\n    )\n  }\n)\n\nOrganicButton.displayName = \"OrganicButton\"\n\nfunction AscendingWall() {\n  return (\n    <svg\n      aria-hidden=\"true\"\n      className=\"-mr-px h-full w-auto shrink-0\"\n      fill=\"none\"\n      viewBox=\"0 0 18 40\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      {...svgShapeAttrs}\n    >\n      <path\n        className={fillOrganic}\n        d=\"M7.101 40H18V0H16C13.594 0 11.4403 1.49249 10.5955 3.74532L0.546698 30.5421C-1.1694 35.1184 2.21356 40 7.101 40Z\"\n      />\n    </svg>\n  )\n}\n\nfunction FlatRoundedRight() {\n  return (\n    <svg\n      aria-hidden=\"true\"\n      className=\"-ml-px h-full w-auto shrink-0\"\n      fill=\"none\"\n      viewBox=\"0 0 10 40\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      {...svgShapeAttrs}\n    >\n      <path\n        className={fillOrganic}\n        d=\"M0 40V0H4C7.31371 0 10 2.68629 10 6V34C10 37.3137 7.31371 40 4 40H0Z\"\n      />\n    </svg>\n  )\n}\n\nfunction DescendingWall() {\n  return (\n    <svg\n      aria-hidden=\"true\"\n      className=\"-ml-px h-full w-auto shrink-0\"\n      fill=\"none\"\n      viewBox=\"0 0 18 40\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      {...svgShapeAttrs}\n    >\n      <path\n        className={fillOrganic}\n        d=\"M10.899 0H0V40H2C4.40603 40 6.55968 38.5075 7.4045 36.2547L17.4533 9.45786C19.1694 4.88161 15.7864 0 10.899 0Z\"\n      />\n    </svg>\n  )\n}\n\nfunction RoundedFlatRight() {\n  return (\n    <svg\n      aria-hidden=\"true\"\n      className=\"-mr-px h-full w-auto shrink-0\"\n      fill=\"none\"\n      viewBox=\"0 0 10 40\"\n      xmlns=\"http://www.w3.org/2000/svg\"\n      {...svgShapeAttrs}\n    >\n      <path\n        className={fillOrganic}\n        d=\"M10 40V0H6C2.68629 0 0 2.68629 0 6V34C0 37.3137 2.68629 40 6 40H10Z\"\n      />\n    </svg>\n  )\n}\n",
      "type": "registry:ui"
    }
  ]
}