Stats

Stats 03 — Data Wall

Minimal Swiss data wall over an edge-masked interactive shader flow field: indexed caption bar, one deliberate 5/4/3 row of three oversized animated stats with hairline rules, and a single ghost link to the methodology.

$ npx shadcn@latest add @ludusvibe/stats-03
Open in v0

Code

Installed to components/sections/stats-03.tsx — it's yours to edit.

"use client"

import * as React from "react"
import { motion } from "motion/react"
import { ArrowUpRight } from "lucide-react"

import { AnimatedNumber } from "@/components/ludus/animated-number"
import { Grain } from "@/components/ludus/grain"
import { ShaderBackground } from "@/components/ludus/shader-background"
import { fadeUp, stagger, viewport } from "@/lib/motion"
import { cn } from "@/lib/utils"

type Stat = {
  label: string
  value: number
  prefix?: string
  suffix?: string
  format?: Intl.NumberFormatOptions
  context: string
}

export type Stats03Props = {
  index?: string
  label?: string
  note?: string
  title?: React.ReactNode
  stats?: Stat[]
  cta?: { label: string; href: string }
  /** Heading element — use "h1" when this is the page's main heading. */
  as?: "h1" | "h2"
  className?: string
}

const DEFAULT_STATS: Stat[] = [
  {
    label: "Average conversion lift",
    value: 23,
    suffix: "%",
    context: "Median uplift across all funnels in the first 90 days.",
  },
  {
    label: "Days to first win",
    value: 12,
    context: "From connecting your data to a shipped, significant test.",
  },
  {
    label: "Revenue recovered",
    value: 84000000,
    prefix: "$",
    format: { notation: "compact", maximumFractionDigits: 0 },
    context: "Leaked checkout and pricing revenue returned to customers in 2025.",
  },
]

export function Stats03({
  index = "03",
  label = "Proof",
  note = "Audited across 2,400+ teams",
  title = "The numbers behind the pitch.",
  stats = DEFAULT_STATS,
  cta = { label: "See the method", href: "#" },
  as: Heading = "h2",
  className,
}: Stats03Props) {
  const [s1, s2, s3] = stats

  const cell = (stat: Stat | undefined, size: "lg" | "md") =>
    stat && (
      <>
        <p className="text-xs tracking-[0.2em] text-muted-foreground uppercase">
          {stat.label}
        </p>
        <p
          className={cn(
            "mt-4 font-medium tracking-tight",
            size === "lg"
              ? "text-[clamp(3rem,7vw,5.5rem)] leading-none"
              : "text-[clamp(2.25rem,5vw,4rem)] leading-none"
          )}
        >
          <AnimatedNumber
            value={stat.value}
            prefix={stat.prefix}
            suffix={stat.suffix}
            format={stat.format}
          />
        </p>
        <p className="mt-3 max-w-[38ch] text-sm text-pretty text-muted-foreground/70">
          {stat.context}
        </p>
      </>
    )

  return (
    <section className={cn("relative overflow-hidden bg-background", className)}>
      <ShaderBackground
        intensity={0.25}
        className="[mask-image:linear-gradient(to_right,black,transparent_60%)]"
      />
      <Grain opacity={0.05} />

      <motion.div
        initial="hidden"
        whileInView="visible"
        viewport={viewport}
        variants={stagger(0.09)}
        className="relative mx-auto max-w-6xl px-6 py-20 md:py-28"
      >
        {/* Swiss index bar */}
        <motion.div
          variants={fadeUp}
          className="flex items-baseline justify-between border-b pb-3 text-xs tracking-[0.2em] text-muted-foreground uppercase"
        >
          <span>
            <span className="text-primary">{index}</span> — {label}
          </span>
          <span className="hidden sm:block">{note}</span>
        </motion.div>

        <motion.div variants={fadeUp} className="mt-10">
          <Heading className="text-[clamp(1.75rem,3.2vw,2.5rem)] font-medium tracking-tight text-balance">
            {title}
          </Heading>
        </motion.div>

        {/* One deliberate row: 5 / 4 / 3 */}
        <div className="mt-12 grid grid-cols-12 gap-x-8 gap-y-12">
          <motion.div
            variants={fadeUp}
            className="col-span-12 border-t pt-5 md:col-span-6 lg:col-span-5"
          >
            {cell(s1, "lg")}
          </motion.div>
          <motion.div
            variants={fadeUp}
            custom={0.05}
            className="col-span-12 border-t pt-5 md:col-span-6 lg:col-span-4"
          >
            {cell(s2, "md")}
          </motion.div>
          <motion.div
            variants={fadeUp}
            custom={0.1}
            className="col-span-12 border-t pt-5 md:col-span-6 lg:col-span-3"
          >
            {cell(s3, "md")}
          </motion.div>
        </div>

        <motion.div variants={fadeUp} custom={0.15} className="mt-12 border-t pt-5">
          <a
            href={cta.href}
            className="inline-flex items-center gap-1.5 text-sm font-medium text-foreground underline-offset-4 hover:text-primary hover:underline"
          >
            {cta.label}
            <ArrowUpRight className="size-4" aria-hidden />
          </a>
        </motion.div>
      </motion.div>
    </section>
  )
}