Hero Section

Product hero with blur-in headline, CTAs and a dashboard mockup that tilts into place.

NewWorkflows 2.0 is here

The operating system for modern revenue teams

Pipeline, forecasting and customer insight in one beautifully fast workspace.

$48.2k+12.4%
2,431+12.4%
64.8%-1.2%

Installation

  1. Install the dependencies

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

    components/ui/hero-section.tsx
    "use client";
    
    import { motion } from "motion/react";
    import { ArrowRight, BarChart3, Home, Inbox, Play, Settings, Users } from "lucide-react";
    
    const ease = [0.22, 1, 0.36, 1] as const;
    
    function DashboardMockup() {
      return (
        <div className="overflow-hidden rounded-2xl border border-zinc-200 bg-white shadow-[0_30px_80px_-20px_rgba(9,9,11,0.25)]">
          <div className="flex items-center gap-1.5 border-b border-zinc-100 px-4 py-3">
            <span className="size-2.5 rounded-full bg-zinc-200" />
            <span className="size-2.5 rounded-full bg-zinc-200" />
            <span className="size-2.5 rounded-full bg-zinc-200" />
            <span className="ml-3 h-5 w-48 rounded-md bg-zinc-100" />
          </div>
          <div className="flex">
            <aside className="hidden w-44 shrink-0 space-y-1 border-r border-zinc-100 p-3 sm:block">
              {[Home, BarChart3, Users, Inbox, Settings].map((Icon, i) => (
                <div key={i} className={`flex items-center gap-2 rounded-lg px-2.5 py-2 text-xs ${i === 1 ? "bg-zinc-900 text-white" : "text-zinc-500"}`}>
                  <Icon className="size-3.5" />
                  <span className={`h-2 rounded ${i === 1 ? "w-14 bg-white/60" : "w-16 bg-zinc-200"}`} />
                </div>
              ))}
            </aside>
            <div className="flex-1 space-y-4 p-5">
              <div className="grid grid-cols-3 gap-3">
                {["$48.2k", "2,431", "64.8%"].map((v, i) => (
                  <div key={v} className="rounded-xl border border-zinc-100 p-3 text-left">
                    <span className="block h-2 w-12 rounded bg-zinc-200" />
                    <span className="mt-2 block text-sm font-semibold text-zinc-900 sm:text-lg">{v}</span>
                    <span className={`text-[10px] font-medium ${i === 2 ? "text-rose-500" : "text-emerald-600"}`}>{i === 2 ? "-1.2%" : "+12.4%"}</span>
                  </div>
                ))}
              </div>
              <div className="rounded-xl border border-zinc-100 p-4">
                <svg viewBox="0 0 400 120" className="h-28 w-full" preserveAspectRatio="none">
                  <defs>
                    <linearGradient id="hero-area" x1="0" x2="0" y1="0" y2="1">
                      <stop offset="0%" stopColor="#2563eb" stopOpacity="0.25" />
                      <stop offset="100%" stopColor="#2563eb" stopOpacity="0" />
                    </linearGradient>
                  </defs>
                  <motion.path
                    d="M0 95 C40 90 60 70 100 72 S160 40 200 48 S270 20 310 30 S370 10 400 8 L400 120 L0 120 Z"
                    fill="url(#hero-area)"
                    initial={{ opacity: 0 }}
                    animate={{ opacity: 1 }}
                    transition={{ delay: 1.4, duration: 0.8 }}
                  />
                  <motion.path
                    d="M0 95 C40 90 60 70 100 72 S160 40 200 48 S270 20 310 30 S370 10 400 8"
                    fill="none"
                    stroke="#2563eb"
                    strokeWidth="2.5"
                    initial={{ pathLength: 0 }}
                    animate={{ pathLength: 1 }}
                    transition={{ delay: 0.8, duration: 1.6, ease: "easeInOut" }}
                  />
                </svg>
              </div>
            </div>
          </div>
        </div>
      );
    }
    
    export function HeroSection() {
      return (
        <section className="relative isolate w-full overflow-hidden px-6 pb-16 pt-20 text-center">
          <div
            aria-hidden
            className="absolute inset-0 -z-10 [background-image:radial-gradient(#e4e4e7_1px,transparent_1px)] [background-size:22px_22px] [mask-image:radial-gradient(ellipse_at_top,black_20%,transparent_70%)]"
          />
          <motion.a
            href="#"
            initial={{ opacity: 0, y: 10 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.6, ease }}
            className="group inline-flex items-center gap-2 rounded-full border border-zinc-200 bg-white py-1 pl-1 pr-3 text-xs font-medium text-zinc-600 shadow-sm"
          >
            <span className="rounded-full bg-blue-600 px-2 py-0.5 text-white">New</span>
            Workflows 2.0 is here
            <ArrowRight className="size-3 transition-transform group-hover:translate-x-0.5" />
          </motion.a>
          <motion.h1
            initial={{ opacity: 0, y: 20, filter: "blur(8px)" }}
            animate={{ opacity: 1, y: 0, filter: "blur(0px)" }}
            transition={{ duration: 0.8, delay: 0.1, ease }}
            className="mx-auto mt-6 max-w-3xl text-balance text-5xl font-semibold tracking-tight text-zinc-900 sm:text-6xl"
          >
            The operating system for modern revenue teams
          </motion.h1>
          <motion.p
            initial={{ opacity: 0, y: 16 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.8, delay: 0.25, ease }}
            className="mx-auto mt-5 max-w-xl text-lg text-zinc-500"
          >
            Pipeline, forecasting and customer insight in one beautifully fast workspace.
          </motion.p>
          <motion.div
            initial={{ opacity: 0, y: 16 }}
            animate={{ opacity: 1, y: 0 }}
            transition={{ duration: 0.8, delay: 0.4, ease }}
            className="mt-8 flex flex-wrap items-center justify-center gap-3"
          >
            <button className="group inline-flex items-center gap-2 rounded-full bg-zinc-900 px-6 py-3 text-sm font-medium text-white transition hover:-translate-y-0.5 hover:bg-zinc-800">
              Start free trial
              <ArrowRight className="size-4 transition-transform group-hover:translate-x-0.5" />
            </button>
            <button className="inline-flex items-center gap-2 rounded-full border border-zinc-200 bg-white px-6 py-3 text-sm font-medium text-zinc-900 transition hover:bg-zinc-50">
              <Play className="size-3.5 fill-current" /> Watch demo
            </button>
          </motion.div>
          <motion.div
            initial={{ opacity: 0, y: 60, rotateX: 18 }}
            animate={{ opacity: 1, y: 0, rotateX: 0 }}
            transition={{ duration: 1.1, delay: 0.5, ease }}
            style={{ transformPerspective: 1400 }}
            className="mx-auto mt-16 max-w-4xl"
          >
            <DashboardMockup />
          </motion.div>
        </section>
      );
    }
    
    export default function Demo() {
      return <HeroSection />;
    }
    
  3. Use it

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