All componentsdisplay
Stat Card
Revenue
$48,240+12.4%
Active users
2,318-3.1%
Uptime
99.98%
Installation
$ npx shadcn@latest add https://deepmoon.dev/r/stat-card.jsonnpm dependencies: lucide-react
Props
StatCardProps
| Prop | Type | Required |
|---|---|---|
| label | React.ReactNode | Yes |
| value | React.ReactNode | Yes |
| delta | StatCardDelta | No |
| icon | React.ReactNode | No |
| sparkline | React.ReactNode | No |
Code
stat-card.tsx
import * as React from "react";
import { ArrowDown, ArrowUp } from "lucide-react";
import { cn } from "@/lib/utils";
export interface StatCardDelta {
value: React.ReactNode;
direction: "up" | "down";
}
export interface StatCardProps extends React.ComponentPropsWithoutRef<"div"> {
label: React.ReactNode;
value: React.ReactNode;
delta?: StatCardDelta;
icon?: React.ReactNode;
sparkline?: React.ReactNode;
}
/** Delta is shape- and color-coded (arrow direction + success/destructive), never color alone. */
export function StatCard({ label, value, delta, icon, sparkline, className, ...props }: StatCardProps) {
return (
<div
className={cn("flex flex-col gap-2 rounded-lg border border-border bg-card p-4 text-card-foreground", className)}
{...props}
>
<div className="flex items-center justify-between gap-2">
<span className="text-sm font-medium text-muted-foreground">{label}</span>
{icon ? (
<span className="text-muted-foreground" aria-hidden="true">
{icon}
</span>
) : null}
</div>
<div className="flex items-end justify-between gap-2">
<span className="text-2xl font-semibold text-foreground">{value}</span>
{delta ? (
<span
className={cn(
"flex items-center gap-0.5 text-xs font-medium",
delta.direction === "up" ? "text-success" : "text-destructive",
)}
>
{delta.direction === "up" ? (
<ArrowUp className="size-3" aria-hidden="true" />
) : (
<ArrowDown className="size-3" aria-hidden="true" />
)}
{delta.value}
</span>
) : null}
</div>
{sparkline ? <div className="mt-1">{sparkline}</div> : null}
</div>
);
}