Default
Monthly revenue
£12,480
Show the codeHide the code
Default, code
<Stat label="Monthly revenue" value="£12,480" />One key number with its label and an optional trend, shown with an arrow icon and words.
These are the real React components. Use them with a mouse, touch or keyboard, and switch the theme and density for every example at once.
Monthly revenue
£12,480
Default, code
<Stat label="Monthly revenue" value="£12,480" />Monthly revenue
£12,480
12% up on September
With a trend, code
<Stat
label="Monthly revenue"
value="£12,480"
trend={{ direction: 'up', text: '12% up on September', sentiment: 'positive' }}
/>Active members
1,204
38 more than last week
Churn
2.1%
0.4 points up
Open tickets
17
No change
Row, code
<div className="grid grid-cols-1 gap-gap-lg sm:grid-cols-3">
<Stat label="Active members" value="1,204" trend={{ direction: 'up', text: '38 more than last week', sentiment: 'positive' }} />
<Stat label="Churn" value="2.1%" trend={{ direction: 'up', text: '0.4 points up', sentiment: 'negative' }} />
<Stat label="Open tickets" value="17" trend={{ direction: 'flat', text: 'No change' }} />
</div>Monthly revenue
£12,480
12% up on September, the best month this year
£11,140 in September
Churn
2.1%
0.4 points up
1.7% in September
Tile, code
function Sparkline() {
return (
<svg viewBox="0 0 120 32" className="h-8 w-full text-chart-1" aria-hidden="true" preserveAspectRatio="none">
<polyline points="0,26 15,22 30,24 45,16 60,18 75,10 90,12 105,6 120,4" fill="none" stroke="currentColor" strokeWidth="2" vectorEffect="non-scaling-stroke" />
</svg>
);
}
<div className="grid max-w-md grid-cols-2 gap-gap-md">
<Card><CardContent>
<Stat label="Monthly revenue" value="£12,480" trend={{ direction: 'up', text: '12% up on September, the best month this year', sentiment: 'positive' }} compare="£11,140 in September" sparkline={<Sparkline />} />
</CardContent></Card>
<Card><CardContent>
<Stat label="Churn" value="2.1%" trend={{ direction: 'up', text: '0.4 points up', sentiment: 'negative' }} compare="1.7% in September" />
</CardContent></Card>
</div>The 6 design tokens Stat reads, with the value each has in the theme and density chosen above. Change a token and the component follows, in Figma and in code.
| Token | Value now | CSS variable |
|---|---|---|
| color.text.danger | … | --sd-color-text-danger |
| color.text.default | … | --sd-color-text-default |
| color.text.secondary | … | --sd-color-text-secondary |
| color.text.success | … | --sd-color-text-success |
| spacing.gap.xs | … | --sd-spacing-gap-xs |
| spacing.stack.xs | … | --sd-spacing-stack-xs |
The npm package isn’t published yet. When it is, this is the install line; until then, this page runs the same build of the package (from commit fa3abf8).
Install
npm i @superduperui/react @superduperui/tokensImport
import { Stat } from "@superduperui/react"Stat also takes the props of the React Aria component it’s built on.
| Prop | Type | What it does |
|---|---|---|
labelrequired | string | What the number is ("Monthly revenue"). |
valuerequired | ReactNode | The value, already formatted ("£12,480"). |
trend | { direction: 'up' | 'down' | 'flat'; text: string; /** Is this direction good? Sets the colour; the words carry the meaning. */ sentiment?: 'positive' | 'negative' | 'neutral' } | Change since the last period, as text ("12% up on September"). Shown with an arrow icon and words, never colour alone. |
compare | ReactNode | The figure it is compared with, in words ("£11,140 in September"). Shown under the trend in the secondary colour. |
sparkline | ReactNode | A small chart under the figures (a sparkline). Decorative, or named by itself; the trend or compare carries the same news in words. |
headingLevel | 2 | 3 | 4 | 5 | 6 | Heading level of the label when the stat starts a section of the outline (2.4.10). Default: not a heading. |
Screen readers announce "Monthly revenue, £12,480, 12% up on September".
WCAG 2.2 AAA criteria the component meets in Comfortable density: 1.4.6, 1.4.9, 2.3.2.
Not interactive: density changes spacing only.
Shared patterns it ships with: 2.4.10 (headingLevel).
| axe-core (WCAG A, AA, AAA and best practice) | 100 runs across every story, theme, density and width: 0 violations |
|---|---|
| Rendered text contrast | 360 text runs: 0 below 7:1, lowest 8.43:1 |
| Target size | 0 targets: 0 under 44px in Comfortable |
| Focus appearance (2.4.13) | 0 focus stops in 0 browser engines: all pass |
Manual passes with VoiceOver and NVDA haven’t been done yet.
The Figma component is Stat, with Trend (Up, Down, Flat); Sentiment (Positive, Negative, Neutral). The Figma library isn’t published yet.
Figma to code: Label → label; Value → value; Trend → trend.direction (Up = "up", Down = "down", Flat = "flat"); Sentiment → trend.sentiment (Positive = "positive", Negative = "negative", Neutral = "neutral"); Trend text → trend.text when Show trend; Compare → compare when Show compare; Sparkline → sparkline.