M
MetricUI
Cards

StatGroup

A row/grid of mini stat cells, perfect for summary bars at the top of dashboards.

import { StatGroup } from "metricui";

Use StatGroup when you need to display multiple metrics in a compact row or grid. It's perfect for summary bars at the top of dashboards — showing key numbers with trend indicators at a glance. For a single prominent metric with sparklines and goals, use KpiCard instead.

Basic Example

Pass an array of stats with label, value, and optional format. Columns auto-detect from the stat count.

Revenue
$0
Users
0
Conversion
0%
<StatGroup
  stats={[
    { label: "Revenue", value: 142300, format: "currency" },
    { label: "Users", value: 12450, format: "number" },
    { label: "Conversion", value: 4.2, format: "percent" },
  ]}
/>

Comparisons & Icons

Add previousValue to each stat item for auto-computed trend badges. Include icon for visual context. Use invertTrend for metrics where down is good (e.g. cost, churn).

This Week

Revenue
$0
+11.2%
Active Users
0
+18.1%
Conversion
0%
+23.5%
Avg. Order
$0
+8.2%
<StatGroup
  title="This Week"
  stats={[
    { label: "Revenue", value: 142800, previousValue: 128400,
      format: "currency", icon: <DollarSign /> },
    { label: "Active Users", value: 3200, previousValue: 2710,
      format: "number", icon: <Users /> },
    { label: "Conversion", value: 4.2, previousValue: 3.4,
      format: "percent", icon: <MousePointerClick /> },
    { label: "Avg. Order", value: 84.6, previousValue: 78.2,
      format: "currency", icon: <TrendingUp /> },
  ]}
/>

Layout & Columns

By default, columns auto-detect from the stat count. Override with the columns prop. Use dense for a more compact layout, and variant to change the card style.

Dense + Ghost variant (2 columns)

Revenue
$0
Users
0
Conversion
0%
Avg. Order
$0

Elevated variant (3 columns)

Uptime
0%
Requests/sec
0
Error Rate
0%
// Dense + ghost variant with explicit columns
<StatGroup stats={stats} dense variant="ghost" columns={2} />

// Elevated variant
<StatGroup stats={stats} variant="elevated" columns={3} />

Data States

StatGroup supports loading state with skeleton placeholders. Also supports legacy change values and string values for pre-formatted data.

Loading

Legacy format (string values + change)

Pageviews
1.2M
Bounce Rate
34.7%
Avg. Session
4m 32s
// Loading state
<StatGroup stats={stats} loading />

// Legacy format with string values and direct change percentages
<StatGroup stats={[
  { label: "Pageviews", value: "1.2M", change: 14.2 },
  { label: "Bounce Rate", value: "34.7%", change: -2.3 },
]} />

Props

PropTypeDescription
stats*
StatItem[]

Array of stat items to display.

title
string

Group title above the grid.

subtitle
string

Group subtitle below the title.

variant
CardVariant

Visual variant: 'default', 'outlined', 'ghost', 'elevated', or any custom string. CSS-variable-driven via [data-variant]. Falls back to config.variant.

dense
boolean

Compact/dense layout. CSS-variable-driven via [data-dense]. Falls back to config.dense.

columns
1 | 2 | 3 | 4 | 5 | 6

Override column count. Auto-detected from stat count by default.

format
FormatOption

Default format applied to all numeric values. Per-stat format overrides this.

loading
boolean

Show skeleton placeholders.

className
string

Additional CSS class names.

classNames
{ root?: string; header?: string; grid?: string; cell?: string; label?: string; value?: string }

Sub-element class name overrides.

id
string

HTML id attribute.

data-testid
string

Test id for testing frameworks.

onStatClick
(stat: StatItem, index: number) => void

Click handler for individual stats.

nullDisplay
NullDisplay

What to show when a stat value is null/undefined. Falls back to config.nullDisplay.

animate
boolean

Enable/disable animations. Currently reserved for future use.

drillDown
boolean | ((event: { stat: StatItem; index: number }) => React.ReactNode)

Enable drill-down on stat click. `true` auto-generates a detail panel. Pass a render function for full control over the panel content. Requires DrillDown.Root wrapper.

drillDownMode
DrillDownMode

Presentation mode for the drill-down panel. "slide-over" (default) slides from the right, full height. "modal" renders centered and compact.

Data Shape

interface StatItem {
  label: string;
  value: string | number;
  change?: number;               // Legacy change percentage
  previousValue?: number;         // For auto-computed comparison
  comparisonMode?: ComparisonMode;
  invertTrend?: boolean;
  format?: FormatOption;
  icon?: React.ReactNode;
}

Notes

  • Uses forwardRef.
  • Grid columns auto-detect from stat count when `columns` is not set.
  • Per-stat `format` overrides the group-level `format`.
  • Supports both legacy `change` (direct percentage) and computed `previousValue` comparisons.

Playground

Experiment with every prop interactively. Adjust the controls on the right to see the component update in real time.

Live Preview

Total Revenue
$0
+11.2%
Active Users
0
+18.1%
Conversion Rate
0%
+23.5%
Avg. Order Value
$0
+8.2%

Code

<StatGroup
  stats={[
    { label: "Total Revenue", value: 142800, previousValue: 128400, format: "currency", icon: <Icon /> },
    { label: "Active Users", value: 3200, previousValue: 2710, format: "number", icon: <Icon /> },
    { label: "Conversion Rate", value: 4.2, previousValue: 3.4, format: "percent", icon: <Icon /> },
    { label: "Avg. Order Value", value: 84.6, previousValue: 78.2, format: "currency", icon: <Icon /> },
  ]}
/>

Props

Adjust props to see the component update in real time

Switch between sample datasets

Override responsive grid columns