CTA Section

Dark call-to-action panel with grid texture and a breathing glow.

Ready to build something great?

Join thousands of teams shipping faster with a design system that feels alive.

Installation

  1. Install the dependencies

    $ npm i motion lucide-react
  2. Copy the source into components/ui/cta-section.tsx

    components/ui/cta-section.tsx
    "use client";
    
    import { motion } from "motion/react";
    import { ArrowRight } from "lucide-react";
    
    type CtaSectionProps = {
      title?: string;
      description?: string;
      primary?: string;
      secondary?: string;
    };
    
    export function CtaSection({
      title = "Ready to build something great?",
      description = "Join thousands of teams shipping faster with a design system that feels alive.",
      primary = "Start building",
      secondary = "Talk to sales",
    }: CtaSectionProps) {
      return (
        <motion.section
          initial={{ opacity: 0, y: 30, scale: 0.98 }}
          whileInView={{ opacity: 1, y: 0, scale: 1 }}
          viewport={{ once: true, amount: 0.4 }}
          transition={{ duration: 0.8, ease: [0.22, 1, 0.36, 1] }}
          className="relative isolate overflow-hidden rounded-[2rem] bg-zinc-950 px-6 py-20 text-center sm:px-16"
        >
          <div
            aria-hidden
            className="absolute inset-0 -z-10 opacity-40 [background-image:linear-gradient(to_right,rgba(255,255,255,0.08)_1px,transparent_1px),linear-gradient(to_bottom,rgba(255,255,255,0.08)_1px,transparent_1px)] [background-size:44px_44px] [mask-image:radial-gradient(ellipse_at_center,black_30%,transparent_75%)]"
          />
          <motion.div
            aria-hidden
            className="absolute left-1/2 top-0 -z-10 h-72 w-[36rem] -translate-x-1/2 -translate-y-1/2 rounded-full bg-blue-600/40 blur-3xl"
            animate={{ opacity: [0.5, 0.9, 0.5], scale: [1, 1.1, 1] }}
            transition={{ duration: 6, repeat: Infinity, ease: "easeInOut" }}
          />
          <h2 className="mx-auto max-w-2xl text-balance text-4xl font-semibold tracking-tight text-white sm:text-5xl">{title}</h2>
          <p className="mx-auto mt-5 max-w-xl text-lg text-zinc-400">{description}</p>
          <div className="mt-10 flex flex-wrap items-center justify-center gap-3">
            <button className="group inline-flex items-center gap-2 rounded-full bg-white px-6 py-3 text-sm font-medium text-zinc-900 transition hover:-translate-y-0.5">
              {primary}
              <ArrowRight className="size-4 transition-transform group-hover:translate-x-0.5" />
            </button>
            <button className="rounded-full px-6 py-3 text-sm font-medium text-white ring-1 ring-white/20 transition hover:bg-white/10">
              {secondary}
            </button>
          </div>
        </motion.section>
      );
    }
    
    export default function Demo() {
      return (
        <div className="w-full max-w-5xl">
          <CtaSection />
        </div>
      );
    }
    
  3. Use it

    The file exports the component and a Demo showing typical usage. Import whichever you need.