Stats

Stats 01 — Stat Band

Full-width bordered band of four animated count-up stats with a subtle primary tint, thin separators and staggered reveals.

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

Code

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

"use client"

import * as React from "react"

import { AnimatedNumber } from "@/components/ludus/animated-number"
import { Reveal } from "@/components/ludus/reveal"
import { cn } from "@/lib/utils"

type Stat = {
  value: number
  label: string
  prefix?: string
  suffix?: string
  /** Intl.NumberFormat options, e.g. `{ notation: "compact" }` for 4B-style values. */
  format?: Intl.NumberFormatOptions
}

export type Stats01Props = {
  stats?: Stat[]
  className?: string
}

const defaultStats: Stat[] = [
  {
    value: 28000,
    suffix: "+",
    label: "Teams shipping with Lumen",
  },
  {
    value: 4_000_000_000,
    suffix: "+",
    format: { notation: "compact" },
    label: "Events processed monthly",
  },
  {
    value: 99.99,
    suffix: "%",
    format: { maximumFractionDigits: 2 },
    label: "Uptime over the last year",
  },
  {
    value: 140,
    suffix: "+",
    label: "Countries with active teams",
  },
]

export function Stats01({ stats = defaultStats, className }: Stats01Props) {
  return (
    <section
      className={cn("relative overflow-hidden border-y bg-card", className)}
    >
      <div
        aria-hidden
        className="absolute inset-0 bg-gradient-to-r from-primary/5 via-transparent to-primary/5"
      />
      <div className="relative mx-auto grid max-w-6xl divide-y divide-border md:grid-cols-4 md:divide-x md:divide-y-0">
        {stats.map((stat, i) => (
          <Reveal
            key={i}
            delay={i * 0.08}
            className="px-6 py-10 text-center md:py-14"
          >
            <div className="font-heading text-4xl font-semibold tracking-tighter md:text-5xl">
              <AnimatedNumber
                value={stat.value}
                prefix={stat.prefix}
                suffix={stat.suffix}
                format={stat.format}
              />
            </div>
            <div className="mt-2 text-sm text-muted-foreground">
              {stat.label}
            </div>
          </Reveal>
        ))}
      </div>
    </section>
  )
}