{
  "$schema": "https://ui.shadcn.com/schema/registry-item.json",
  "name": "integration-01",
  "title": "Integration 01",
  "description": "Dark-themed integration showcase with a curved connection path drawn between tool logos. Use it on landing pages to visually communicate how your product fits into your users' existing toolchain.",
  "dependencies": [],
  "registryDependencies": [
    "https://shadcnship.com/r/social-icons.json"
  ],
  "files": [
    {
      "path": "src/registry/blocks/integration-01/integration.tsx",
      "content": "import { cn } from \"@/lib/utils\";\nimport {\n  ChatGptIcon,\n  ClaudeIcon,\n  GeminiIcon,\n  GoogleIcon,\n  NotionIcon,\n  ReplitIcon,\n  SlackIcon,\n  SupabaseIcon,\n} from \"@/registry/blocks/social-icons/icons\";\n\ninterface IntegrationIcon {\n  icon: React.ReactNode;\n  className?: string;\n}\n\ninterface Testimonial {\n  quote: string;\n  author: string;\n  role: string;\n  avatar?: string;\n}\n\ninterface Integration01Props {\n  label?: string;\n  title?: string;\n  description?: string;\n  integrations?: IntegrationIcon[];\n  testimonial?: Testimonial;\n  className?: string;\n}\n\nconst IntegrationIconBubble = ({\n  icon,\n  className,\n  size = \"md\",\n}: IntegrationIcon & { size?: \"sm\" | \"md\" | \"lg\" }) => {\n  const sizeClasses = {\n    sm: \"size-8\",\n    md: \"size-8 md:size-10\",\n    lg: \"size-8 md:size-12\",\n  };\n\n  return (\n    <div\n      className={cn(\n        \"flex items-center justify-center rounded-full border bg-white/5 backdrop-blur-xs\",\n        sizeClasses[size],\n        className,\n      )}\n    >\n      {icon}\n    </div>\n  );\n};\n\nconst Integration01 = ({\n  label = \"Seamless integrations\",\n  title = \"Works with your favorite tools\",\n  description = \"Connect with the apps you already use. Our components integrate seamlessly with your existing workflow, from AI assistants to collaboration tools.\",\n  integrations = [\n    { icon: <SlackIcon className=\"w-full p-1.5\" /> },\n    { icon: <SupabaseIcon className=\"w-full p-1.5\" /> },\n    { icon: <ChatGptIcon className=\"w-full p-1.5 dark:invert\" /> },\n    { icon: <ClaudeIcon className=\"w-full p-1.5\" /> },\n    { icon: <NotionIcon className=\"w-full p-1.5\" /> },\n    { icon: <ReplitIcon className=\"w-full p-1.5\" /> },\n    { icon: <GoogleIcon className=\"w-full p-1.5\" /> },\n    { icon: <GeminiIcon className=\"w-full p-1.5\" /> },\n    { icon: <ReplitIcon className=\"w-full p-1.5\" /> },\n  ],\n  testimonial = {\n    quote:\n      \"The integration with our existing stack was effortless. We connected Slack, Notion, and our AI tools in minutes. It just works.\",\n    author: \"Sarah Chen\",\n    role: \"Engineering Lead at Acme\",\n    avatar:\n      \"https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=100&h=100&fit=crop&crop=face\",\n  },\n  className,\n}: Integration01Props) => {\n  const getPositionOnCurve = (index: number, total: number) => {\n    const t = index / (total - 1);\n    const p0 = { x: 0, y: 75 };\n    const p1 = { x: 50, y: -50 };\n    const p2 = { x: 100, y: 75 };\n    const x =\n      Math.pow(1 - t, 2) * p0.x +\n      2 * (1 - t) * t * p1.x +\n      Math.pow(t, 2) * p2.x;\n    const y =\n      Math.pow(1 - t, 2) * p0.y +\n      2 * (1 - t) * t * p1.y +\n      Math.pow(t, 2) * p2.y;\n    return { x, y };\n  };\n\n  const mobileIntegrations = integrations.slice(0, 5);\n\n  const renderIntegrationArc = (\n    icons: IntegrationIcon[],\n    className?: string,\n  ) => {\n    const count = icons.length;\n    return (\n      <div className={cn(\"relative aspect-3/1\", className)}>\n        <svg\n          className=\"absolute inset-0 size-full overflow-visible\"\n          viewBox=\"0 0 100 100\"\n          preserveAspectRatio=\"none\"\n          fill=\"none\"\n        >\n          <path\n            d=\"M 0 75 Q 50 -50 100 75\"\n            stroke=\"currentColor\"\n            strokeWidth=\"1\"\n            fill=\"none\"\n            className=\"text-border\"\n            vectorEffect=\"non-scaling-stroke\"\n          />\n        </svg>\n        {icons.map((integration, index) => {\n          const pos = getPositionOnCurve(index, count);\n          const isCenter = index === Math.floor(count / 2);\n          return (\n            <div\n              key={index}\n              className=\"absolute -translate-x-1/2 -translate-y-1/2\"\n              style={{ left: `${pos.x}%`, top: `${pos.y}%` }}\n            >\n              <IntegrationIconBubble\n                icon={integration.icon}\n                size=\"md\"\n                className={isCenter ? \"border-primary\" : \"\"}\n              />\n            </div>\n          );\n        })}\n        <div className=\"pointer-events-none absolute inset-y-0 -left-8 w-1/4 bg-linear-to-r from-background to-transparent md:w-24\" />\n        <div className=\"pointer-events-none absolute inset-y-0 -right-8 w-1/4 bg-linear-to-l from-background to-transparent md:w-24\" />\n      </div>\n    );\n  };\n\n  return (\n    <section\n      className={cn(\n        \"container mx-auto overflow-hidden px-8 py-12 md:py-24\",\n        className,\n      )}\n    >\n      <div className=\"mx-auto flex max-w-2xl flex-col items-center gap-4 text-center\">\n        <p className=\"text-sm font-semibold tracking-widest text-muted-foreground uppercase\">\n          {label}\n        </p>\n        <h2 className=\"text-4xl font-medium tracking-tight md:text-5xl\">\n          {title}\n        </h2>\n        <p className=\"text-muted-foreground md:text-lg\">{description}</p>\n      </div>\n      <div className=\"relative mx-auto mt-12 max-w-5xl\">\n        {renderIntegrationArc(mobileIntegrations, \"md:hidden\")}\n        {renderIntegrationArc(integrations, \"hidden md:block\")}\n        <div className=\"mx-auto mt-8 max-w-lg text-center md:absolute md:right-0 md:-bottom-6 md:left-0 lg:bottom-10\">\n          <p className=\"text-sm font-medium md:text-base\">\n            &ldquo;{testimonial.quote}&rdquo;\n          </p>\n          <div className=\"mt-4 flex items-center justify-center gap-3\">\n            {testimonial.avatar && (\n              <img\n                src={testimonial.avatar}\n                alt={testimonial.author}\n                className=\"size-10 rounded-full object-cover\"\n              />\n            )}\n            <div className=\"flex flex-col gap-0.5 text-left\">\n              <p className=\"text-sm font-medium\">{testimonial.author}</p>\n              <p className=\"text-xs text-muted-foreground\">\n                {testimonial.role}\n              </p>\n            </div>\n          </div>\n        </div>\n      </div>\n    </section>\n  );\n};\n\nexport default Integration01;\n",
      "type": "registry:component",
      "target": "components/integration-01.tsx"
    }
  ],
  "meta": {
    "image": "/r/previews/integration-01.webp",
    "imageDark": "/r/previews/integration-01-dark.webp",
    "prose": {
      "about": "Integration 01 is a dark-themed integration showcase that displays a curved SVG connection path drawn between your product logo in the center and surrounding tool or partner logos. It visually communicates ecosystem compatibility and how your product sits at the center of a user's workflow. Built with SVG path animations and Tailwind CSS, the connection lines animate on load. Tool logos are configurable as image or inline SVG components.",
      "whenToUse": [
        "Platform or middleware products where sitting between existing tools is the core value proposition",
        "Developer tools or APIs that integrate with a recognizable ecosystem of services",
        "Landing pages where showing logos of popular integrations is more persuasive than describing APIs",
        "Products competing in markets where integration breadth is a buying criterion"
      ],
      "notes": "Use official brand SVG logos sourced from the respective brand asset pages. Distorted or low-resolution logos undermine the credibility the section is designed to build.",
      "faqs": [
        {
          "question": "Are the logos real brand assets?",
          "answer": "You should supply official SVG logos from each brand's asset page — low-resolution or distorted logos undermine the credibility the section builds."
        },
        {
          "question": "Does the connection animation require JavaScript?",
          "answer": "It uses SVG path animations combined with Tailwind CSS, triggered on load."
        },
        {
          "question": "How many integration logos can it display?",
          "answer": "Logos are configurable as image or inline SVG components arranged around the center path — keep the count reasonable to avoid visual clutter."
        }
      ]
    }
  },
  "categories": [
    "content"
  ],
  "type": "registry:block"
}