All blocks

Stats cards

Dashboard KPI tiles.

Preview

Sessions
24,821

+12.4% vs last month

Conversion
3.9%

+0.6pp vs last month

Avg session
2m 14s

-8s vs last month

Bounce rate
42.1%

-1.2pp vs last month

Code

import { ArrowDown, ArrowUp } from "lucide-react"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@smaller-earth/ui"

const stats = [
  { label: "Sessions", value: "24,821", delta: "+12.4%", trend: "up" },
  { label: "Conversion", value: "3.9%", delta: "+0.6pp", trend: "up" },
  { label: "Avg session", value: "2m 14s", delta: "-8s", trend: "down" },
  { label: "Bounce rate", value: "42.1%", delta: "-1.2pp", trend: "up" },
] as const

export function StatsCards() {
  return (
    <div className="grid w-full gap-3 sm:grid-cols-2 lg:grid-cols-4">
      {stats.map((s) => (
        <Card key={s.label}>
          <CardHeader>
            <CardDescription>{s.label}</CardDescription>
            <CardTitle className="text-3xl tabular-nums">{s.value}</CardTitle>
          </CardHeader>
          <CardContent>
            <p className={"inline-flex items-center gap-1 text-sm " + (s.trend === "up" ? "text-success" : "text-destructive")}>
              {s.trend === "up" ? <ArrowUp className="size-3.5" /> : <ArrowDown className="size-3.5" />}
              {s.delta} vs last month
            </p>
          </CardContent>
        </Card>
      ))}
    </div>
  )
}