A compact, semantic row of key metrics that adapts from one to four columns.
- Visitors
- 48.2k
- Last 30 days
- Signups
- 1,208
- 2.5% conversion
- Active
- 892
- 74% retained
import { KpiRow, KpiItem } from "@/components/ballmac/kpi-row"
export default function KpiRowDemo() {
return (
<KpiRow columns={3} className="w-full max-w-xl">
<KpiItem label="Visitors" value="48.2k" detail="Last 30 days" />
<KpiItem label="Signups" value="1,208" detail="2.5% conversion" />
<KpiItem label="Active" value="892" detail="74% retained" />
</KpiRow>
)
}Installation
$ pnpm dlx shadcn@latest add @ballmac/kpi-rowCopy the source into your project.
components/ballmac/kpi-row.tsx// Ballmac UI: KPI Row. https://ui.ballmac.com/components/kpi-row import * as React from "react" import { cn } from "@/lib/utils" type KpiRowProps = React.ComponentProps<"dl"> & { /** Number of columns at wide widths. */ columns?: 2 | 3 | 4 } type KpiItemProps = React.ComponentProps<"div"> & { /** Metric label. */ label: string /** Metric value. */ value: React.ReactNode /** Supporting context or comparison. */ detail?: React.ReactNode } function KpiRow({ className, columns = 3, ...props }: KpiRowProps) { return ( <dl data-slot="kpi-row" data-columns={columns} className={cn( "bg-card grid min-w-0 grid-cols-1 overflow-hidden rounded-xl border border-border sm:grid-cols-2 data-[columns=3]:lg:grid-cols-3 data-[columns=4]:lg:grid-cols-4", className, )} {...props} /> ) } function KpiItem({ className, label, value, detail, ...props }: KpiItemProps) { return ( <div data-slot="kpi-item" className={cn( "flex min-w-0 flex-col gap-2 border-b border-border p-5 last:border-b-0 sm:border-b-0 sm:border-e sm:last:border-e-0", className, )} {...props} > <dt className="text-muted-foreground text-xs font-medium uppercase tracking-wide"> {label} </dt> <dd className="truncate text-2xl font-semibold tabular-nums tracking-tight"> {value} </dd> {detail && <dd className="text-muted-foreground text-xs">{detail}</dd>} </div> ) } export { KpiRow, KpiItem, type KpiRowProps, type KpiItemProps }Update the import paths to match your project setup.
Usage
import { KpiRow, KpiItem } from "@/components/ballmac/kpi-row"The full example is in the Code tab above.
Examples
States and variants
- Requests
- 2.4M
- Success rate
- 99.9%
- Trailing seven days
import { KpiRow, KpiItem } from "@/components/ballmac/kpi-row"
export default function KpiRowStates() {
return (
<KpiRow columns={2} className="w-full max-w-md">
<KpiItem label="Requests" value="2.4M" />
<KpiItem
label="Success rate"
value="99.9%"
detail="Trailing seven days"
/>
</KpiRow>
)
}API reference
<KpiRow>
| Prop | Type | Default |
|---|---|---|
columnsNumber of columns at wide widths. | 2 | 3 | 4 | 3 |
<KpiItem>
| Prop | Type | Default |
|---|---|---|
label*Metric label. | string | — |
value*Metric value. | React.ReactNode | — |
detailSupporting context or comparison. | React.ReactNode | — |
Also accepts the standard attributes of its root element.
Accessibility
| Key | Action |
|---|---|
| None | Static content is announced with semantic structure |
Use with AI
A compact, semantic row of key metrics that adapts from one to four columns. With the shadcn MCP server set up (guide), ask your agent:
Add the Ballmac UI KPI Row (@ballmac/kpi-row) to this project with the shadcn MCP, then use it where it fits.
Use it for
- Show several related metrics together
Not for
- Use Stat Card when each metric needs more context
Registry JSON: https://ui.ballmac.com/r/kpi-row.json
Credits
Free to use in personal and commercial projects.
- npm
- None
- Registry
- shadcn/utils
Pairs well with
Stat Card
A metric card with a clear comparison trend, optional visual, and readable value hierarchy.
Activity Feed
A compact actor and action feed with timestamps and an empty state.
Audio Player
A podcast-style audio player: play and pause, skip back and forward, a scrubber with chapter ticks, a named current chapter and a speed control. Works with a real file or as a silent demo.
Avatar Circles
Overlapping avatars that spread on hover, lift individually with a name and role tooltip, show presence, fall back to initials and end in a +N count that can be a button.