Interactive Answers
Stat Grid
KPI cards with rolling numbers, deltas and sparklines for a quick summary answer.
2 variantsMIT
Preview
October at a glance
Updated live from the billing and usage APIs
Monthly recurring revenue
$47.1k
+9.6%, better
Goal $60k79%
Weekly active teams
1,188
+7.9%, bettervs. last week
Goal 1,50079%
Median response time
1.38s
-14.8%, betteropus-5.5
Target 1.2s87%
Logo churn
1.9%
-20.8%, better
Target 1.5%79%
Installation
Copies the component into components/ui and installs its dependencies and theme tokens.
pnpm dlx shadcn@latest add https://tuffui.com/r/stat-grid.jsonUsage
Pass your own data and wire the callbacks to your agent runtime.
import { StatGrid } from "@/components/ui/stat-grid";
// A summary answer: the agent fetched metrics and shows the headline numbers.
export function MetricsAnswer({ m }: { m: Metrics }) {
return (
<StatGrid
title="October at a glance"
data={[
{ id: "mrr", label: "MRR", value: formatMoney(m.mrr), delta: m.mrrDelta, trend: m.mrrTrend },
{
id: "latency",
label: "Median response time",
value: `${m.p50}s`,
delta: m.p50Delta,
higherIsBetter: false, // a drop is good news
},
]}
/>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| data* | Stat[] | — | Two to four stats. Values are preformatted strings and roll when they change. |
| title | string | — | Optional header above the cards. |
| subtitle | string | — | Secondary line under the title. |
| sparklines | boolean | true | Draw a trend line for stats that carry `trend`. |
| onSelect | (stat: Stat) => void | — | Makes each card a button, e.g. to open a chart for that metric. |
| className | string | — | Extra classes for the root element. |
type Stat = {
id: string;
label: string;
value: string; // "$48.2k", "1,204", "1.31s"
delta?: number; // % change; shown with an arrow and better/worse text
higherIsBetter?: boolean; // default true; set false for latency, churn, cost
trend?: number[]; // oldest first
goal?: { ratio: number; label: string }; // striped progress toward a target
hint?: string; // e.g. "vs. last week"
};