Component Contract
Stat / KPI
A headline figure with a short label — used singly or grouped into a stat strip.
Live Demo
Single stats (light)
Rendered
Stat strip (dark band — e.g. under a hero)
1. Summary
| Component name | Stat / KPI |
|---|---|
| AEM resource type | caat/components/stat |
| Tier | Base (single stat) · the strip is a composite layout of stats |
| Purpose | Present a key figure (value + label) with strong visual weight, alone or in a strip. |
| Variants | Single (light) · Stat strip (dark band) |
| Status | New |
| Replaces | .caat-stat-strip/.caat-stat-item previously defined inside Hero |
Used by
- Hero — the stat strip beneath the hero (now composed from this component).
- Data Visualization — headline figures (candidate to adopt
.caat-stat). - Marketing/landing pages (e.g. Pensions Matter template).
2. Design Tokens
| Token | Role |
|---|---|
--caat-color-text-heading | Value (light context) |
--caat-color-text-muted | Label (light context) |
--caat-color-bg-brand / --caat-color-text-inverse | Stat strip dark band + value |
--caat-radius-lg | Strip corners when composed in a hero |
3. Authoring Fields
| Field | Type | Required | Notes |
|---|---|---|---|
| Value | Text | Yes | The figure; a trailing unit can be wrapped in <small> |
| Label | Text | Yes | Short caption (1–3 words) |
| Layout | Select | Yes | Single · Strip (multifield of stats) |
4. Validation Rules
| Rule | Behaviour |
|---|---|
| Strip: maximum 3 stats | The strip multifield rejects a 4th entry — four columns break at tablet widths (768–991 px). Need more figures? Use stat cards in a grid instead. |
| Accessible label | The strip container requires an aria-label (e.g. "Results by the numbers"). |
5. Content Guidance
- Lead with the number; keep labels to 1–3 words ("Plan assets", "Funded").
- Use a strip of 2–3 stats (3 max) for impact — four breaks at tablet widths. More figures belong in stat cards or a table.
- Use an icon when it improves recognition, but keep the icon slot desktop-only so the stacked tablet/mobile layout stays compact.
- Round figures for scannability ("$4.2B", "95k+") and keep precise data for charts/tables.
6. Semantic HTML
<!-- Single -->
<div class="caat-stat">
<span class="caat-stat__value">$4.2<small>B</small></span>
<span class="caat-stat__label">Plan assets</span>
</div>
<!-- Strip (max 3 stats; aria-label required) -->
<div class="caat-stat-strip" role="group" aria-label="Key figures">
<div class="caat-stat">
<span class="caat-stat__icon" aria-hidden="true"><i class="bi bi-piggy-bank-fill"></i></span>
<span class="caat-stat__value">$4.2<small>B</small></span>
<span class="caat-stat__label">Plan assets</span>
</div>
<div class="caat-stat">…</div>
</div>
If a stat is decorative duplication of nearby prose, mark it aria-hidden; otherwise the value + label read together.
7. CSS Contract
| Selector | Purpose |
|---|---|
.caat-stat | Single stat wrapper (centred) |
.caat-stat__icon | Optional leading icon, shown above the value on desktop only |
.caat-stat__value / __label | Figure / caption |
.caat-stat-strip | Dark band row of stats, with dividers |
.caat-stat-strip--bleed | Full-bleed background for the strip while keeping the stats aligned to the page container |
.caat-stat-item strong/span | Legacy element API (kept for back-compat) |
8. Accessibility
| Requirement | Implementation |
|---|---|
| Reading order | Value precedes label in the DOM so they announce together. |
| Contrast | Light: heading/muted on white (AA). Dark strip: white value + dimmed-white label on brand navy (AA verified). |
| Not interactive | Stats are non-focusable; if a stat links somewhere, wrap it in a real link/Button. |
| Abbreviations | Spell out units in the label, not just the <small> glyph, where ambiguous. |
| Icons | Icon slot is optional and hidden below desktop; do not rely on it to convey meaning because it disappears on tablet/mobile. |
9. SEO
Transient / structural UI with no indexable content of its own — no SEO markup required. Ensure any content this component wraps or reveals stays server-rendered and crawlable.
10. Analytics
Analytics are captured through the shared data-analytics-component attribute on the component root (emitted automatically) and reported to the central data layer. Event names and payloads follow the organisation's standard analytics schema — defined centrally with the analytics team, not invented per component — so no bespoke tracking is specified here.
11. AEM Implementation Notes
- Resource type:
caat/components/stat; the strip is a multifield of stat items. - Sling model exposes
value,unit,label, and (strip)items+layout. - Hero composes the strip variant via Sling delegation.
12. Dialog Model (cq:dialog)
Not authored directly. The stat is a sub-element emitted and configured by its host component (or generated from page structure), so it has no standalone cq:dialog — any options are exposed through the host component's dialog.
13. QA Checklist
| # | Check | Pass? |
|---|---|---|
| 1 | Single stat: dark value + muted label on light | |
| 2 | Strip: dark band, white value, dimmed label, dividers between | |
| 3 | Strip stacks vertically on mobile with horizontal dividers | |
| 4 | Value precedes label in DOM | |
| 5 | Hero strip keeps rounded bottom corners (composition) |
14. Definition of Done
- Token-driven; AA verified on light and dark.
- Optional desktop-only icon slot renders above each stat without affecting tablet/mobile stacking.
- Hero refactored to compose it (was Hero-internal CSS).
- Responsive strip verified mobile→desktop.
- QA checklist signed off.