Stat
Display a labelled metric with an optional change indicator, plus a responsive group wrapper.
Installation
npx shadcn@latest add @redpanda/statpnpm dlx shadcn@latest add @redpanda/statyarn dlx shadcn@latest add @redpanda/statbunx shadcn@latest add @redpanda/statnubx shadcn@latest add @redpanda/stataube dlx shadcn@latest add @redpanda/statUsage
Stat renders a single label and value pair. StatGroup arranges several Stats into a responsive grid, ideal for KPI strips like a cluster overview. Stats in a group use CSS subgrid so labels, values, and sublabels row-align across the strip even when label lengths differ.
import { Stat, StatGroup } from "@/components/redpanda-ui/stat"
<StatGroup columns={4}>
<Stat label="Brokers" value="3" mono />
<Stat label="Topics" value="128" tone="muted" mono />
<Stat label="Throughput" value="42 MB/s" size="lg" tone="success" mono />
<Stat label="Under-replicated" value="4" tone="warning" mono />
</StatGroup>
Anatomy
Stat Structure:
┌───────────────────────────────────┐
│ <StatGroup> (responsive grid) │
│ ┌───────────────────────────────┐ │
│ │ <Stat> │ │
│ │ • label (uppercase caption) │ │
│ │ • value (+ optional delta) │ │
│ │ • sublabel (optional) │ │
│ └───────────────────────────────┘ │
└───────────────────────────────────┘
Variants
Sizes
<Stat label="Small" value="42" size="sm" />
<Stat label="Medium" value="42" size="md" />
<Stat label="Large" value="42" size="lg" />
Tones
<Stat label="Default" value="42" tone="default" />
<Stat label="Muted" value="42" tone="muted" />
<Stat label="Success" value="42" tone="success" />
<Stat label="Warning" value="42" tone="warning" />
<Stat label="Destructive" value="42" tone="destructive" />
Monospaced
Use mono for tabular figures that should not jitter as values update.
<Stat label="Throughput" value="42 MB/s" mono />
Delta indicator
delta adds an optional change affordance. direction drives both the icon and the default color (up → success, down → destructive, neutral → muted). Override with tone.
<Stat label="Throughput" value="42 MB/s" delta={{ value: "+12%", direction: "up" }} />
<Stat label="Consumer lag" value="312" delta={{ value: "-4.3%", direction: "down" }} />
<Stat label="Partitions" value="640" delta={{ value: "0%", direction: "neutral" }} />
Sublabel
sublabel hangs a muted secondary line below the value (e.g. a partition count under a topic count). It does not affect the value’s baseline, so stats with and without a sublabel stay top-aligned inside a StatGroup.
<Stat label="Topics" value="6" sublabel="6 partitions" size="lg" />
Linked label
labelLink turns the label into a link. Pass a single link element with no children — the label text and a trailing arrow are injected, and the caption styling plus a hover affordance are merged onto it. Client-side routing stays with the caller, so any link component works (<a>, TanStack/Next <Link>, etc.).
<Stat label="Topics" value="6" labelLink={<a href="/topics" />} />
<Stat label="Topics" value="6" labelLink={<Link to="/clusters/$clusterId/topics" params={{ clusterId }} />} />
Group columns and gap
Each columns value is a ramp on the group’s own width, not the viewport’s, so a group in a card, a panel or a narrow column steps down instead of squeezing its values. 3 shows 3 columns from a 448px group and 4 shows 4 from 672px; 6 shows 3 from 672px and 6 from 896px. Below those, 3 shows 1 column and the others show 2.
<StatGroup columns={2} gap="sm">{/* ... */}</StatGroup>
<StatGroup columns={3} gap="md">{/* ... */}</StatGroup>
<StatGroup columns={4} gap="lg">{/* ... */}</StatGroup>
<StatGroup columns={6} gap="md">{/* ... */}</StatGroup>
Row alignment
Stats in a group render on a shared CSS subgrid, so labels, values, and sublabels each occupy a common row. When one label wraps to two lines, its neighbors’ values stay on the same baseline instead of drifting up — no fixed label heights needed.
Props
Stat
| Prop | Type | Default | Description |
|---|---|---|---|
label |
string |
— | Caption shown above the value (uppercased, muted). |
value |
React.ReactNode |
— | The metric value. |
sublabel |
React.ReactNode |
— | Muted secondary line below the value. |
size |
'sm' | 'md' | 'lg' |
'md' |
Value type scale. lg is bold with tight tracking. |
tone |
'default' | 'muted' | 'success' | 'warning' | 'destructive' |
'default' |
Value color. |
mono |
boolean |
false |
Use monospaced, tabular figures for the value. |
delta |
{ value: string; direction: 'up' | 'down' | 'neutral'; tone? } |
— | Optional change indicator. |
labelLink |
React.ReactElement |
— | Link element (no children) that the label renders as, with a trailing arrow. |
testId |
string |
— | Maps to data-testid. |
Also accepts all div props.
StatGroup
| Prop | Type | Default | Description |
|---|---|---|---|
columns |
2 | 3 | 4 | 6 |
4 |
Column count at full width; steps down with the group’s own width. |
gap |
'sm' | 'md' | 'lg' |
'md' |
Gap between stats. |
testId |
string |
— | Maps to data-testid. |
Also accepts all div props. Children should be Stat items.