Metric card
A compact summary for a number that needs context.
datasummary
Preview
Metric card preview
Live · keyboard ready
Monthly revenue+15.2%
48,250 USDvs 41,900 last month
When to use
- A single plain number with odometer style rolling digits, such as uptime or orders.
- Numbers that update live and should roll in the direction they moved.
When not to use
- Use stat-card for preformatted strings, trend arrows, tones, and icons.
- Use sparkline when the trend over time matters more than the latest value.
- Use animated-counter for a number without a card around it.
shadcn CLI
Also installs (2)
- manicat-foundation
- animated-counter
Manual install(+)
registry.jsonjson
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "metric-card",
"type": "registry:ui",
"title": "Metric card",
"description": "A compact summary for a number that needs context.",
"categories": [
"data"
],
"dependencies": [
"motion"
],
"registryDependencies": [
"https://manicat.viraza.net/r/manicat-foundation.json",
"https://manicat.viraza.net/r/animated-counter.json"
],
"files": [
{
"path": "registry/components/metric-card/metric-card.tsx",
"type": "registry:component",
"target": "@components/manicat/metric-card/metric-card.tsx"
},
{
"path": "registry/components/metric-card/metric-card.module.css",
"type": "registry:component",
"target": "@components/manicat/metric-card/metric-card.module.css"
},
{
"path": "registry/components/animated-counter/animated-counter.tsx",
"type": "registry:component",
"target": "@components/manicat/animated-counter/animated-counter.tsx"
},
{
"path": "registry/components/animated-counter/animated-counter.module.css",
"type": "registry:component",
"target": "@components/manicat/animated-counter/animated-counter.module.css"
}
],
"docs": "Docs and live preview: https://uiarc.dev/components/metric-card",
"meta": {
"tier": "free",
"kind": "component",
"docs": "https://manicat.viraza.net/components/metric-card",
"markdown": "https://uiarc.dev/components/metric-card/markdown",
"tags": [
"data",
"summary"
]
}
}Usage
Install the component, then copy this into your app. Change the content and the props to fit your screen.
example.tsxtsx
"use client";
import { useState } from "react";
import { MetricCard } from "@/components/manicat/metric-card/metric-card";
import { Button } from "@/components/manicat/button/button";
export function MetricCardExample() {
const [revenue, setRevenue] = useState(48250);
return (
<div className="flex flex-wrap items-center gap-4">
<MetricCard label="Monthly revenue" value={revenue} suffix=" USD" context="vs 41,900 last month" change="+15.2%" />
<Button size="sm" variant="secondary" onClick={() => setRevenue((value) => value + 1250)}>
Add 1,250
</Button>
</div>
);
}
Examples
Real screens rather than isolated props. Switch to Code to copy a whole example into your project.
Revenue metric A headline number with context and change, updating live.
Revenue metric
A headline number with context and change, updating live. preview
Live · keyboard ready
Monthly revenue+15.2%
48,250 USDvs 41,900 last month
revenue-metric-a-headline-number-with-context-and-change-updating-live-.tsxtsx
"use client";
import { useState } from "react";
import { Button } from "@/components/manicat/button/button";
import { MetricCard } from "@/components/manicat/metric-card/metric-card";
export function MetricCardRevenueExample() {
const [revenue, setRevenue] = useState(48250);
return (
<div className="flex flex-wrap items-center gap-4">
<MetricCard label="Monthly revenue" value={revenue} suffix=" USD" context="vs 41,900 last month" change="+15.2%" />
<Button size="sm" variant="secondary" onClick={() => setRevenue((value) => value + 1250)}>
Add 1,250
</Button>
</div>
);
}
Accessibility
- Renders an article; the number is read as plain text through a visually hidden copy.
- The change chip is plain text, so write the direction into it (+ or -) rather than relying on color.
- It does not announce updates; wrap it in a live region if values change while people watch.
Motion
- The value uses animated-counter: digits roll on view and turn the way the number moved.
- Label, context, and change copy roll in from the direction the number moved, and the chip width springs.
- Reduced motion jumps the digits and swaps copy with a quick fade.
Responsive behavior
- Below 380px the padding tightens and the change chip wraps under the label instead of crowding it.
- Copy lines stay on one line and clip, so keep label and context short.
Performance
- Digits roll with animated-counter and a ResizeObserver drives the chip width spring; a dashboard row of cards is fine.
Notes for AI
- Use when the value is a plain number and you want the rolling digits. Use stat-card for preformatted strings, trend arrows, tones, and icons.
- value must be a number; put units in suffix and formatting-free context in context.