Skip to content

Layout

Stat

A card-less statistic with a label, a big number, a unit, a trend and a hint, sharing KpiCard typography.

<script>
  import { Stat } from "@codeatlasdev/ui";
</script>

<Stat label="Leads this week" value="128" hint="12 more than last week" />
<Stat label="Reply rate" value="18" unit="%" trend={-2.4} size="sm" />
<Stat label="Churn" value="5.2" unit="%" trend={-1.8} trendTone="positive-down" />

Use Stat for a plain number inside a card, a panel or a flex/grid row. It has no background, border or padding and inherits its colour from the container, so it never nests a second box. Use KpiCard when the metric needs its own card: a KpiCard is a Stat inside a Card, so both share one set of typography tokens.

It renders a description list (<dl>): the label is the <dt>, the value the <dd>, so assistive tech reads the label as the name of the number. The label is one line and truncates with an ellipsis in a narrow container (390px); the value uses tabular numerals and never wraps. Text colours are --ca-text-secondary (label), --ca-text-primary (value) and --ca-text-hint (hint). Place several Stats side by side with a grid or flex wrapper; do not wrap each one in a Card.

trend is a relative percent change that you compute: trend={12.5} shows +12.5%. A metric that went from 80 to 90 passes trend={12.5}, not 10.

A trend is good news when it goes up by default: a rise is green, a fall red. For a metric where down is good (churn, cost, latency) set trendTone="positive-down": the arrow still follows the sign, the colour flips, and the accessible label says “better” or “worse” (Trend: -1.8%, better; Tendência: -1.8%, melhor in pt-BR). trendTone="neutral" shows the change without judging it. A zero change is always neutral. Do not drop trend and write the delta in hint to avoid a wrong colour.

Stats in a card

Three card-less stats in one Card, with hint, unit and trend.

This week

Leads this week
128
12 more than last week
Reply rate
18%
↓-2.4%
Goal: 25%
Booked calls
9
↑+12.5%
Code
svelte
<script lang="ts">
  import { Card, Stat } from '@codeatlasdev/ui';
</script>

<Card title="This week" headingLevel={3} class="stats-card">
  <div class="row">
    <Stat label="Leads this week" value="128" hint="12 more than last week" />
    <Stat label="Reply rate" value="18" unit="%" trend={-2.4} hint="Goal: 25%" />
    <Stat label="Booked calls" value="9" trend={12.5} />
  </div>
</Card>

<style>
  :global(.stats-card) { width: 100%; max-width: 640px; }
  .row { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: var(--ca-space-5); }
</style>

Props

PropTypeDefaultDescription
labelstring–What is measured. One line, truncates with an ellipsis.
valuestring | number–The number. Tabular numerals, never wraps.
unitstring–Unit shown after the value (`%`, `ms`, `users`).
hintstring–Secondary caption below the value.
trendnumber–Relative percent change, already computed: `12.5` renders `+12.5%` and `-2.4` renders `-2.4%` (one decimal). It is not an absolute difference, so pass `(now - before) / before * 100`, not `now - before`. The arrow follows the sign (up, down, none for zero). Announced as "Trend: +12.5%".
trendTone'positive-up' | 'positive-down' | 'neutral'–Which direction of `trend` is good news. Without it a rise is green and a fall red; `'positive-up'` says the same and `'positive-down'` flips it (churn, cost, latency); `'neutral'` judges neither. Setting it adds "better" or "worse" to the accessible label. Zero is always neutral.
size'sm' | 'md' | 'lg''md'Value size: 17px, 24px or 36px.
align'start' | 'center''start'Text alignment.
skeletonbooleanfalseLoading placeholder with the exact size of the loaded stat, announced as busy. See Skeleton.
classstring''Extra class names.