integrations.tsx
"use client"
import { motion } from "motion/react"
import { useReducedMotion } from "@/hooks/use-reduced-motion"
import { Icons } from "@/components/ui/icons"
type IntegrationItem = {
label: string
icon: React.ComponentType<React.HTMLAttributes<SVGElement>>
description: string
x: number
y: number
}
const stages: IntegrationItem[] = [
{
label: "Gemini",
description: "Imagine",
icon: Icons.Gemini,
x: 100,
y: 334,
},
{
label: "Cursor",
description: "Create",
icon: Icons.Cursor,
x: 262,
y: 254,
},
{
label: "Next.js",
description: "Build",
icon: Icons.Nextjs,
x: 424,
y: 174,
},
{ label: "GitHub", description: "Ship", icon: Icons.GitHub, x: 586, y: 94 },
]
export function Integration() {
const reduceMotion = useReducedMotion()
return (
<section
aria-label="Integrations"
className="@container mx-auto w-full max-w-6xl px-6 py-16 lg:py-24"
>
<div className="grid items-center gap-10 @3xl:grid-cols-2 @3xl:gap-16">
<header className="flex max-w-md flex-col items-start gap-5">
<p className="text-xs font-medium tracking-widest text-muted-foreground uppercase">
Integrations
</p>
<h1 className="text-3xl font-semibold tracking-tight text-balance sm:text-5xl">
Keep your
<br />
momentum.
</h1>
<p className="text-base text-pretty text-muted-foreground">
From the first spark to the next release, bring the right tool to
every step of your process.
</p>
</header>
<div className="min-w-0">
<svg viewBox="0 0 686 546" className="w-full" aria-hidden="true">
<path
d="M100 334H157Q181 334 181 310V278Q181 254 205 254H319Q343 254 343 230V198Q343 174 367 174H481Q505 174 505 150V118Q505 94 529 94H586"
fill="none"
className="stroke-border"
strokeWidth={1.5}
/>
{stages.map(({ label, description, icon: Icon, x, y }, index) => (
<g key={label} transform={`translate(${x} ${y})`}>
<path
d="M0 62V108"
className="stroke-border/50"
strokeDasharray="2 5"
/>
<foreignObject
x={-58}
y={-58}
width={116}
height={116}
overflow="visible"
>
<motion.div
whileHover={reduceMotion ? undefined : { y: -8 }}
transition={{ duration: 0.3 }}
className="flex size-full items-center justify-center rounded-4xl bg-card shadow-elevated-md"
>
<Icon className="size-12" />
</motion.div>
</foreignObject>
<foreignObject x={-66} y={112} width={132} height={88}>
<div className="flex flex-col items-center gap-1 text-center">
<span className="text-xl text-muted-foreground @3xl:text-base">
0{index + 1} / {label}
</span>
<span className="text-3xl font-medium @3xl:text-2xl">
{description}
</span>
</div>
</foreignObject>
</g>
))}
</svg>
<ol className="sr-only">
{stages.map(({ label, description }) => (
<li key={label}>
{description} with {label}
</li>
))}
</ol>
</div>
</div>
</section>
)
}


























