← StatsOpen in v0
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-01Code
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>
)
}