Centered CTA
Original · freecentred CTA band
Copy prompt gives Claude Code, Cursor or v0 a ready-to-paste prompt that recreates this exact component.
npx shadcn@latest add https://webinnoventix.com/r/ctax-centered.json"use client";
import { useId, useState } from "react";
import type { FormEvent } from "react";
import { motion, useReducedMotion } from "motion/react";
type Status = "idle" | "error" | "success";
export default function CtaxCentered() {
const reduce = useReducedMotion();
const emailId = useId();
const errId = useId();
const [email, setEmail] = useState("");
const [status, setStatus] = useState<Status>("idle");
function handleSubmit(event: FormEvent<HTMLFormElement>) {
event.preventDefault();
const valid = /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email.trim());
if (!valid) {
setStatus("error");
return;
}
setStatus("success");
}
const reveal = (delay: number) =>
reduce
? { initial: false as const }
: {
initial: { opacity: 0, y: 22 },
whileInView: { opacity: 1, y: 0 },
viewport: { once: true, margin: "-70px" },
transition: {
duration: 0.65,
delay,
ease: [0.16, 1, 0.3, 1] as [number, number, number, number],
},
};
return (
<section className="relative w-full overflow-hidden bg-gradient-to-b from-white to-slate-100 px-6 py-24 sm:py-32 dark:from-slate-950 dark:to-slate-900">
<style>{`
@keyframes ctaxc-drift {
0% { transform: translate3d(0, 0, 0) scale(1); }
33% { transform: translate3d(4%, -6%, 0) scale(1.08); }
66% { transform: translate3d(-5%, 4%, 0) scale(0.95); }
100% { transform: translate3d(0, 0, 0) scale(1); }
}
@keyframes ctaxc-drift-slow {
0% { transform: translate3d(0, 0, 0) scale(1); }
50% { transform: translate3d(-6%, 5%, 0) scale(1.12); }
100% { transform: translate3d(0, 0, 0) scale(1); }
}
@keyframes ctaxc-ping {
0% { transform: scale(1); opacity: 0.7; }
70% { transform: scale(2.6); opacity: 0; }
100% { transform: scale(2.6); opacity: 0; }
}
@keyframes ctaxc-sheen {
0% { transform: translateX(-140%) skewX(-18deg); }
60%, 100% { transform: translateX(260%) skewX(-18deg); }
}
.ctaxc-blob-a { animation: ctaxc-drift 22s ease-in-out infinite; }
.ctaxc-blob-b { animation: ctaxc-drift-slow 28s ease-in-out infinite; }
.ctaxc-blob-c { animation: ctaxc-drift 26s ease-in-out infinite reverse; }
.ctaxc-ping { animation: ctaxc-ping 2.8s cubic-bezier(0,0,0.2,1) infinite; }
.ctaxc-sheen { animation: ctaxc-sheen 4.5s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) {
.ctaxc-blob-a, .ctaxc-blob-b, .ctaxc-blob-c,
.ctaxc-ping, .ctaxc-sheen { animation: none !important; }
}
`}</style>
{/* Atmospheric background — gradients, blobs, and a faint grid */}
<div aria-hidden="true" className="pointer-events-none absolute inset-0 overflow-hidden">
<div className="ctaxc-blob-a absolute -top-24 left-1/2 h-[34rem] w-[34rem] -translate-x-[70%] rounded-full bg-indigo-400/40 blur-3xl dark:bg-indigo-600/30" />
<div className="ctaxc-blob-b absolute -top-16 left-1/2 h-[30rem] w-[30rem] -translate-x-[10%] rounded-full bg-violet-400/40 blur-3xl dark:bg-violet-600/25" />
<div className="ctaxc-blob-c absolute -bottom-32 left-1/2 h-[32rem] w-[32rem] -translate-x-1/2 rounded-full bg-sky-300/40 blur-3xl dark:bg-sky-600/20" />
<svg
className="absolute inset-0 h-full w-full text-slate-900/[0.05] dark:text-white/[0.06]"
xmlns="http://www.w3.org/2000/svg"
>
<defs>
<pattern id="ctaxc-grid" width="44" height="44" patternUnits="userSpaceOnUse">
<path d="M44 0H0V44" fill="none" stroke="currentColor" strokeWidth="1" />
</pattern>
<radialGradient id="ctaxc-fade" cx="50%" cy="42%" r="60%">
<stop offset="0%" stopColor="white" stopOpacity="1" />
<stop offset="100%" stopColor="white" stopOpacity="0" />
</radialGradient>
<mask id="ctaxc-mask">
<rect width="100%" height="100%" fill="url(#ctaxc-fade)" />
</mask>
</defs>
<rect width="100%" height="100%" fill="url(#ctaxc-grid)" mask="url(#ctaxc-mask)" />
</svg>
</div>
<div className="relative mx-auto flex max-w-3xl flex-col items-center text-center">
{/* Eyebrow badge */}
<motion.span
{...reveal(0)}
className="inline-flex items-center gap-2 rounded-full border border-slate-200 bg-white/70 px-4 py-1.5 text-xs font-medium tracking-wide text-slate-700 shadow-sm backdrop-blur dark:border-white/10 dark:bg-white/5 dark:text-slate-200"
>
<span className="relative flex h-2 w-2">
<span className="ctaxc-ping absolute inline-flex h-full w-full rounded-full bg-emerald-500" />
<span className="relative inline-flex h-2 w-2 rounded-full bg-emerald-500" />
</span>
New in Cadence — automated project handoffs
</motion.span>
{/* Headline */}
<motion.h2
{...reveal(0.08)}
className="mt-7 text-4xl font-semibold tracking-tight text-slate-900 sm:text-6xl dark:text-white"
>
Ship the work,
<br className="hidden sm:block" />{" "}
<span className="bg-gradient-to-r from-indigo-600 via-violet-600 to-sky-500 bg-clip-text text-transparent dark:from-indigo-400 dark:via-violet-400 dark:to-sky-400">
skip the status meeting
</span>
</motion.h2>
{/* Subhead */}
<motion.p
{...reveal(0.16)}
className="mt-6 max-w-xl text-base leading-relaxed text-slate-600 sm:text-lg dark:text-slate-300"
>
Cadence folds scattered updates into one live source of truth, so your
team spends its hours building the product instead of reporting on it.
</motion.p>
{/* Email capture form */}
<motion.div {...reveal(0.24)} className="mt-10 w-full max-w-md">
{status === "success" ? (
<div
role="status"
aria-live="polite"
className="flex items-center justify-center gap-3 rounded-2xl border border-emerald-300/70 bg-emerald-50 px-5 py-4 text-sm font-medium text-emerald-800 dark:border-emerald-500/30 dark:bg-emerald-500/10 dark:text-emerald-200"
>
<svg
aria-hidden="true"
viewBox="0 0 20 20"
fill="currentColor"
className="h-5 w-5 shrink-0 text-emerald-600 dark:text-emerald-400"
>
<path
fillRule="evenodd"
d="M16.7 5.3a1 1 0 0 1 0 1.4l-7.5 7.5a1 1 0 0 1-1.4 0L3.3 9.7a1 1 0 1 1 1.4-1.4l3.3 3.29 6.8-6.8a1 1 0 0 1 1.4 0Z"
clipRule="evenodd"
/>
</svg>
You're in. Check your inbox to set up your workspace.
</div>
) : (
<form onSubmit={handleSubmit} noValidate className="flex flex-col gap-3">
<div className="flex flex-col gap-3 sm:flex-row">
<label htmlFor={emailId} className="sr-only">
Work email address
</label>
<input
id={emailId}
type="email"
inputMode="email"
autoComplete="email"
placeholder="you@company.com"
value={email}
onChange={(event) => {
setEmail(event.target.value);
if (status === "error") setStatus("idle");
}}
aria-invalid={status === "error"}
aria-describedby={status === "error" ? errId : undefined}
className="min-w-0 flex-1 rounded-xl border border-slate-300 bg-white px-4 py-3 text-sm text-slate-900 shadow-sm outline-none transition placeholder:text-slate-400 focus:border-indigo-500 focus:ring-2 focus:ring-indigo-500/40 aria-[invalid=true]:border-rose-400 aria-[invalid=true]:ring-2 aria-[invalid=true]:ring-rose-400/40 dark:border-white/15 dark:bg-white/5 dark:text-white dark:placeholder:text-slate-500"
/>
<button
type="submit"
className="group relative inline-flex items-center justify-center gap-2 overflow-hidden rounded-xl bg-slate-900 px-6 py-3 text-sm font-semibold text-white shadow-lg shadow-indigo-500/20 outline-none transition hover:bg-slate-800 focus-visible:ring-2 focus-visible:ring-indigo-500 focus-visible:ring-offset-2 focus-visible:ring-offset-white dark:bg-white dark:text-slate-900 dark:hover:bg-slate-100 dark:focus-visible:ring-offset-slate-950"
>
<span className="ctaxc-sheen pointer-events-none absolute inset-y-0 -left-1 w-1/3 bg-white/25 blur-md dark:bg-slate-900/10" />
<span className="relative">Start free</span>
<svg
aria-hidden="true"
viewBox="0 0 20 20"
fill="none"
className="relative h-4 w-4 transition-transform duration-200 group-hover:translate-x-0.5"
>
<path
d="M4 10h11m0 0-4-4m4 4-4 4"
stroke="currentColor"
strokeWidth="1.8"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</button>
</div>
{status === "error" ? (
<p id={errId} role="alert" className="text-left text-xs font-medium text-rose-600 dark:text-rose-400">
Please enter a valid work email so we can send your invite.
</p>
) : (
<p className="text-left text-xs text-slate-500 dark:text-slate-400">
14-day trial · no credit card · cancel anytime.
</p>
)}
</form>
)}
<div className="mt-4 flex items-center justify-center">
<a
href="#demo"
className="inline-flex items-center gap-1.5 text-sm font-medium text-slate-700 underline-offset-4 transition hover:text-indigo-600 hover:underline dark:text-slate-300 dark:hover:text-indigo-400"
>
Or book a 20-minute demo
<svg aria-hidden="true" viewBox="0 0 20 20" fill="none" className="h-3.5 w-3.5">
<path
d="M7 5l5 5-5 5"
stroke="currentColor"
strokeWidth="1.8"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</a>
</div>
</motion.div>
{/* Social proof */}
<motion.div
{...reveal(0.32)}
className="mt-12 flex flex-col items-center gap-4 sm:flex-row sm:gap-6"
>
<div className="flex items-center">
<div className="flex -space-x-3">
{[
"from-indigo-400 to-violet-500",
"from-sky-400 to-indigo-500",
"from-emerald-400 to-sky-500",
"from-amber-400 to-rose-500",
"from-violet-400 to-fuchsia-500",
].map((swatch, index) => (
<span
key={index}
className={`h-9 w-9 rounded-full bg-gradient-to-br ${swatch} ring-2 ring-white dark:ring-slate-950`}
/>
))}
</div>
<span className="ml-4 text-sm font-medium text-slate-700 dark:text-slate-300">
3,200+ product teams
</span>
</div>
<span className="hidden h-5 w-px bg-slate-300 sm:block dark:bg-white/15" />
<div className="flex items-center gap-2">
<div className="flex" aria-hidden="true">
{Array.from({ length: 5 }).map((_, index) => (
<svg key={index} viewBox="0 0 20 20" fill="currentColor" className="h-4 w-4 text-amber-400">
<path d="M10 1.5l2.6 5.3 5.9.85-4.25 4.14 1 5.86L10 15.9l-5.25 2.75 1-5.86L1.5 7.65l5.9-.85L10 1.5Z" />
</svg>
))}
</div>
<span className="text-sm text-slate-600 dark:text-slate-400">
<span className="font-semibold text-slate-800 dark:text-slate-200">4.9/5</span>{" "}
across 600+ reviews
</span>
</div>
</motion.div>
{/* Assurance row */}
<motion.ul
{...reveal(0.4)}
className="mt-8 flex flex-wrap items-center justify-center gap-x-6 gap-y-2 text-xs font-medium text-slate-500 dark:text-slate-400"
>
{["SOC 2 Type II", "99.99% uptime SLA", "Migrate in a day"].map((item) => (
<li key={item} className="inline-flex items-center gap-1.5">
<svg aria-hidden="true" viewBox="0 0 20 20" fill="currentColor" className="h-3.5 w-3.5 text-emerald-500">
<path
fillRule="evenodd"
d="M16.7 5.3a1 1 0 0 1 0 1.4l-7.5 7.5a1 1 0 0 1-1.4 0L3.3 9.7a1 1 0 1 1 1.4-1.4l3.3 3.29 6.8-6.8a1 1 0 0 1 1.4 0Z"
clipRule="evenodd"
/>
</svg>
{item}
</li>
))}
</motion.ul>
</div>
</section>
);
}Dependencies
Licence
Built by Web Innoventix. Free for personal and commercial use, no attribution required.
Built by Web Innoventix
Need a custom interface, a full website, or SEO that gets you cited by AI? We design, build and rank it end to end.
Get a free quoteSimilar components
Browse all →
Gradient CTA
OriginalA bold gradient call-to-action banner with two buttons.

Full-Bleed Dark CTA
OriginalA full-bleed dark call-to-action banner with a live status badge, subtle grid backdrop and a primary plus secondary button pair to drive discovery calls.

Split CTA With Lead Form
OriginalA two-column call-to-action that pairs a benefit checklist with an inline name, email and message form for capturing qualified leads directly in the section.

Newsletter CTA With Stats
OriginalA newsletter sign-up call-to-action combining an inline email subscribe form with a three-cell social-proof stat strip to boost conversions.

Aurora Glow CTA Banner
OriginalA full-bleed dark call-to-action banner with a rotating aurora gradient, floating orbs and a shine-on-hover button, with staggered blur-in text that reveals on scroll.

Animated Border Beam CTA
OriginalAn email-capture call-to-action card wrapped in a rotating conic-gradient border beam, with staggered reveal, animated shine text and an inline success state on submit.

Marquee Ribbon CTA
OriginalA dark call-to-action band framed by two infinite scrolling tag ribbons with a continuously flowing animated-gradient button and staggered centre content.

Split CTA
Originalsplit CTA with image side

Gradient Band CTA
Originalgradient CTA band

Newsletter CTA
OriginalCTA with newsletter input

App Download CTA
Originalapp download CTA with store buttons

Stats CTA CTA
OriginalCTA with supporting stats

