Stat
A KPI card with animated count-up value, label, trend indicator, and sparkline slot. Built for dashboards and metrics displays.
Basic
A KPI metric card with animated count-up value, label, trend indicator (up/down/neutral), and an optional sparkline slot.
Installation
Install the component via the CLI in one command.
npx @work-rjkashyap/unified-ui add statpnpm dlx @work-rjkashyap/unified-ui add statnpx @work-rjkashyap/unified-ui add statbunx @work-rjkashyap/unified-ui add statIf you haven't initialized your project yet, run npx @work-rjkashyap/unified-ui init first. See the CLI docs for details.
Or install the full package
Use this approach if you prefer to install the entire design system as a dependency instead of copying individual components.
npm install @work-rjkashyap/unified-uipnpm add @work-rjkashyap/unified-uiyarn add @work-rjkashyap/unified-uibun add @work-rjkashyap/unified-uiAnatomy
import { Stat } from "@work-rjkashyap/unified-ui";Basic Usage
Pass a label and value to render a minimal stat card. Numeric values get the count-up animation automatically.
<Stat label="Total Users" value={12430} />
<Stat label="Revenue" value={84200} prefix="$" />
<Stat label="Uptime" value={99.9} suffix="%" />Trend Indicator
Use trend to show a directional arrow icon and trendLabel for the description text. up renders green, down renders red, and neutral renders muted.
| Trend | Icon | Color | Use Case |
|---|---|---|---|
up | Trend Up ↗ | --success | Revenue, users, positive metrics |
down | Trend Down ↘ | --danger | Errors, churn, negative metrics |
neutral | — | --muted-fg | Unchanged metrics, no change |
Prefix & Suffix
Add a prefix for currency symbols or a suffix for units. Both are rendered as part of the animated count-up value.
String Values
When value is a string, no count-up animation plays — the value is rendered as-is. This is useful for non-numeric KPIs.
Sparkline Slot
Pass any ReactNode to the sparkline prop to render a chart or visual in the top-right corner of the card. The slot is 32px tall and right-aligned.
Without Animation
Set animated={false} to disable the count-up and slide animations entirely.
<Stat
label="Total Users"
value={12430}
trend="up"
trendLabel="+120 today"
animated={false}
/>Dashboard Grid
A typical 4-up KPI grid layout.
const stats = [
{
label: "Total Revenue",
value: 128400,
prefix: "$",
trend: "up",
trendLabel: "+12% this month",
},
{
label: "Active Users",
value: 8230,
trend: "up",
trendLabel: "+340 this week",
},
{
label: "Avg. Order Value",
value: 72,
prefix: "$",
trend: "up",
trendLabel: "+$4 vs last month",
},
{
label: "Churn Rate",
value: 1.8,
suffix: "%",
trend: "down",
trendLabel: "-0.2% this month",
},
];
<div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
{stats.map((stat) => (
<Stat key={stat.label} {...stat} />
))}
</div>;Props
| Prop | Type | Default | Description |
|---|---|---|---|
label | ReactNode | — | Required. The metric label rendered above the value. |
value | string | number | — | Required. The metric value. Numbers get count-up animation. |
previousValue | number | — | Previous value (reserved for future delta calculation). |
trend | "up" | "down" | "neutral" | — | Directional trend indicator. |
trendLabel | ReactNode | — | Descriptive text rendered next to the trend icon. |
sparkline | ReactNode | — | Optional mini chart slot rendered in the top-right corner. |
prefix | string | — | Text prepended to the value (e.g., "$"). |
suffix | string | — | Text appended to the value (e.g., "%", " users"). |
animated | boolean | true | Whether to enable count-up and entrance animations. |
className | string | — | Additional CSS classes on the root card element. |
Motion
- Count-up — Numeric values animate from
0to the target usingframer-motion'sanimate()with a 1s ease-out curve ([0.4, 0, 0.2, 1]). The displayed integer is derived fromuseMotionValue+useTransform. - Value entrance — The value block uses the
countUppreset (y: 12 → 0,opacity: 0 → 1). - Trend entrance — The trend row uses
slideUpSmwith a 300ms delay, staggering after the value. - Reduced motion — All animations are disabled when
prefers-reduced-motionis active. The final value is displayed immediately.
Accessibility
- The animated count-up span is wrapped in
aria-live="polite"andaria-atomic="true"so screen readers announce the final value after animation completes. - Trend icons are
aria-hidden="true"— context is conveyed viatrendLabeltext. - The card element is a plain
<div>— wrap in a<section>or addaria-labelwhen used in a landmark region.
Design Tokens
| Token | Usage |
|---|---|
--card | Card background |
--border | Card border |
--success | Upward trend color |
--danger | Downward trend color |
--muted-fg | Label and neutral trend color |
--radius-lg | Card border radius (rounded-lg) |