CTA 02
CTA 02 é um componente de botão para React e Tailwind CSS, da biblioteca Eldora UI, com licença MIT. Copia e cola no teu projeto.
Eldora UI
MIT
buttons
O que é
CTA 02 é um componente de botão para React e Tailwind CSS, da biblioteca Eldora UI, com licença MIT. Copia e cola no teu projeto.
Como usar
Abre o componente no catálogo, carrega em copiar, e cola no teu projeto. O prompt copiado leva o código e as regras para o teu agente o reproduzir sem alterar nada.
Cinco cópias grátis por mês. Sem cartão.
Precisa de
npm i motion/react next-themes
Licença
Este componente vem de Eldora UI e é redistribuído sob a licença MIT, que permite uso comercial. O aviso de copyright viaja com o código.
CTA 02
import CtaPage from "@/registry/blocks/cta-02/components/cta-02"
export default function Cta02Page() {
return (
<div className="flex min-h-screen w-full flex-col items-center justify-center px-4">
<CtaPage />
</div>
)
}
import Link from "next/link"
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import { Grid } from "@/registry/eldoraui/grid"
import { Icons } from "./icons"
import { OrbitingCircles } from "./orbiting-circle"
const OribitingCirclesAnimation = ({ className }: { className?: string }) => {
return (
<div
className={cn(
"bg-background absolute inset-0 z-0 flex flex-col overflow-visible",
className
)}
aria-hidden
>
<div className="relative flex h-[50%] min-h-[240px] w-full shrink-0 items-center justify-center overflow-visible">
<div className="from-background pointer-events-none absolute bottom-0 left-0 z-20 h-20 w-full bg-gradient-to-t to-transparent" />
<div className="from-background pointer-events-none absolute top-0 left-0 z-20 h-10 w-full bg-gradient-to-b to-transparent" />
<div className="relative -mt-60 flex h-full w-full items-center justify-center">
<OrbitingCircles
index={0}
iconSize={150}
radius={150}
reverse
speed={1}
>
<Icons.boat />
<Icons.supabase />
<Icons.figma />
</OrbitingCircles>
<OrbitingCircles index={1} iconSize={150} radius={300} speed={0.5}>
<Icons.workos />
<Icons.runwayml />
<Icons.gemini />
</OrbitingCircles>
<OrbitingCircles
index={2}
iconSize={150}
radius={440}
reverse
speed={0.5}
>
<Icons.vercel />
<Icons.replit />
<Icons.posthog />
</OrbitingCircles>
</div>
</div>
</div>
)
}
export default function CtaPage() {
return (
<Grid
columns={1}
rows={1}
height="min-h-[36rem]"
width="w-full"
showPlusIcons={false}
>
<section className="relative min-h-[36rem] w-full overflow-hidden">
<OribitingCirclesAnimation />
<div
className="via-background/40 to-background/70 pointer-events-none absolute inset-0 z-10 bg-gradient-to-b from-transparent from-35% via-55% to-100% backdrop-blur-[0.8px]"
aria-hidden
/>
<div className="relative z-20 flex min-h-[36rem] flex-col items-center justify-center gap-6 px-4 py-12">
<h2 className="text-foreground max-w-2xl text-center text-3xl font-bold tracking-tight sm:text-4xl md:text-5xl">
Connect your Current Stack and Start Automating
</h2>
<Button
asChild
size="lg"
className="bg-foreground text-background hover:bg-foreground/90 rounded-xl border-0 px-8 py-6 text-base font-medium shadow-[0_4px_14px_rgba(0,0,0,0.25)] transition-colors dark:shadow-[0_4px_14px_rgba(255,255,255,0.2)]"
>
<Link href="#">Start Building for Free</Link>
</Button>
</div>
</section>
</Grid>
)
}
"use client"
import React, { useEffect, useRef, useState } from "react"
import { cubicBezier, HTMLMotionProps, motion, useInView } from "motion/react"
import { cn } from "@/lib/utils"
export interface OrbitingCirclesProps extends HTMLMotionProps<"div"> {
className?: string
children?: React.ReactNode
reverse?: boolean
duration?: number
delay?: number
radius?: number
path?: boolean
iconSize?: number
speed?: number
index?: number
startAnimationDelay?: number
once?: boolean
}
export function OrbitingCircles({
className,
children,
reverse,
duration = 20,
radius = 160,
path = true,
iconSize = 30,
speed = 1,
index = 0,
startAnimationDelay = 0,
once = false,
...props
}: OrbitingCirclesProps) {
const calculatedDuration = duration / speed
const ref = useRef(null)
const isInView = useInView(ref, { once: true })
const [shouldAnimate, setShouldAnimate] = useState(false)
useEffect(() => {
if (isInView) {
setShouldAnimate(true)
}
}, [isInView])
return (
<>
{path && (
<motion.div ref={ref}>
{shouldAnimate && (
<motion.div
initial={{ scale: 0, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
transition={{
duration: 0.8,
ease: [0.23, 1, 0.32, 1],
delay: index * 0.2 + startAnimationDelay,
type: "spring",
stiffness: 120,
damping: 18,
mass: 1,
}}
className="pointer-events-none absolute inset-0"
style={{
width: radius * 2,
height: radius * 2,
left: `calc(50% - ${radius}px)`,
top: `calc(50% - ${radius}px)`,
}}
>
<div
className={cn(
"size-full rounded-full",
"border border-black/[0.08] dark:border-white/[0.08]",
"bg-gradient-to-b from-black/[0.06] from-0% via-black/[0.02] via-50% to-transparent",
"dark:from-white/[0.06] dark:via-white/[0.02] dark:to-transparent",
className
)}
/>
</motion.div>
)}
</motion.div>
)}
{shouldAnimate &&
React.Children.map(children, (child, index) => {
const angle = (360 / React.Children.count(children)) * index
return (
<div
style={
{
"--duration": calculatedDuration,
"--radius": radius * 0.98,
"--angle": angle,
"--icon-size": `${iconSize}px`,
} as React.CSSProperties
}
className={cn(
"animate-orbit absolute z-20 flex size-[var(--icon-size)] transform-gpu items-center justify-center rounded-full p-1",
{ "[animation-direction:reverse]": reverse }
)}
>
<motion.div
key={`orbit-child-${index}`}
initial={{ scale: 0, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
transition={{
duration: 0.5,
delay: 0.6 + index * 0.2 + startAnimationDelay,
ease: cubicBezier(0, 0, 0.58, 1),
type: "spring",
stiffness: 120,
damping: 18,
mass: 1,
}}
{...props}
>
{child}
</motion.div>
</div>
)
})}
</>
)
}