Skip to main content

StatCard

StatCard

A headline metric with its change against a previous value and an optional trend

Tags: chart stat kpi metric delta dashboard reporting

View Demo

The StatCard shows one headline metric: a label, a formatted value, its change against a previous value (coloured by whether the direction is good), an optional hint and definition, and an optional sparkline trend. Group several with StatGroup for a KPI row.

Svelte only (@classic-homes/charts-svelte); React support is pending.

Import​

<script>
  import { StatCard } from '@classic-homes/charts-svelte';
</script>

Basic Usage​

<script>
  import { StatCard } from '@classic-homes/charts-svelte';
</script>

<StatCard
  label="Closings YTD"
  value={412}
  valueFormat="integer"
  delta={{ previous: 368, label: 'vs last year' }}
  trend={[28, 31, 35, 33, 38, 41, 44, 47]}
/>

Props​

Prop Type Default Description
label string required Metric name
value number | string | null | undefined required The value; numbers are formatted with valueFormat, strings shown as-is
valueFormat ValueFormat - Preset ('number', 'integer', 'compact', 'currency', 'currencyCents', 'percent', 'percentValue', 'days'), Intl.NumberFormatOptions or a function
locale string 'en-US' Locale for valueFormat and the change percentage
delta StatDelta - Change against a previous value
hint string - Secondary text under the value
definition string - Definition of the metric, shown in an info tooltip beside the label (and to screen readers)
href string - Make the card a link
trend (number | null)[] - Trend values, drawn as a sparkline
trendVariant 'line' | 'area' | 'bar' 'line' Sparkline variant
tone 'default' | 'success' | 'warning' | 'destructive' 'default' Tone of the value itself, e.g. to flag a breached threshold
emptyValue string '—' Text shown when the value is missing
loading boolean false Show a loading placeholder
class string - Custom CSS class

Data Structure​

interface StatDelta {
  previous: number | null | undefined; // The value compared against
  current?: number | null; // Defaults to the card's value when it is a number
  display?: 'percent' | 'absolute' | 'both'; // Default 'percent'
  goodWhen?: 'up' | 'down' | 'none'; // Which direction is coloured as good (default 'up')
  label?: string; // Text after the change (defaults to "vs <previous>")
}

The change is shown with an arrow and sign. A rise is green when goodWhen is 'up' and red when it is 'down'; 'none' keeps it neutral. A change from zero has no percentage, so 'percent' falls back to the absolute change. No change is shown when previous (or the current value) is missing.

Examples​

Lower Is Better​

<StatCard
  label="Avg cycle time"
  value={112}
  valueFormat="days"
  delta={{ previous: 121, goodWhen: 'down', display: 'both', label: 'vs Q2' }}
  definition="Days from permit to close, for homes closed in the period"
  trend={[124, 121, 119, 118, 115, 112]}
/>

Currency, Linked, with a Hint​

<StatCard
  label="Gross margin per home"
  value={86400}
  valueFormat="currency"
  delta={{ previous: 81200, display: 'absolute' }}
  hint="Closed homes, trailing 90 days"
  href="/reports/margin"
/>

Flagging a Threshold​

<StatCard
  label="Warranty requests over 30 days"
  value={23}
  tone={23 > 15 ? 'destructive' : 'default'}
  delta={{ previous: 18, goodWhen: 'down' }}
/>

Loading and Missing Values​

<StatCard label="Backlog" value={backlog} loading={!loaded} emptyValue="n/a" />

Accessibility​

  • The definition is available to screen readers as visually hidden text after the label
  • Direction is shown with ▲/▼ and a sign as well as colour
  • The trend sparkline is labelled "<label> trend"
  • loading sets aria-busy on the card
  • With href the card is a focusable link with a visible focus ring
On this page