Skip to content

Components · Charts

DeltaIndicator

An up, down or flat change with sign, arrow and a spoken sentence; colour follows which direction is better.

@rookcom/monarch-react/chartsComponent

Better, worse and lower-is-better

up 12.4% vs last month, betterdown 5.2% vs last month, worsedown 58 ms vs last week, betterup $1,250.00 in spend, worse

Usage examples

Flat, no data and pill

Purpose

Shows how a value moved between two periods, the same way everywhere: arrow, signed percentage or amount, an optional comparison, and green or red depending on whether that direction is good.

Use when

  • A period-over-period change next to a KPI, in a table cell or in a list row.
  • Changes where down is good, such as costs, response time, churn or a ranking position.
  • Generating the same wording for a chart summary or aria-label (formatDelta).

Avoid when

  • Showing a trend over many points: use a sparkline or line chart.
  • Status that is not a change (healthy, failing): use StatusBadge.

Design principles

  • Meaning never depends on colour: the arrow, the sign (+ or a true minus) and the spoken direction carry it; colour only says better or worse.
  • goodDirection decides colour, not the sign: a 12% fall in cost is green.
  • Nothing to compare is not zero: a missing or zero baseline shows "No earlier data", not "+∞%" or "0%".
  • A change that rounds to zero when written ("0%") is shown as "No change", never "+0%".
  • Formatting is Intl.NumberFormat with the given locale; currency goes through Money.

API reference

import { DeltaIndicator, formatDelta } from '@rookcom/monarch-react/charts';
ExportKindRenderingRoot class
DeltaIndicatorcomponentserver-safe.mn-delta-indicator
formatDeltautilityserver-safe–

The ref and native <span> attributes go to the root.

formatDelta(options) returns { value, direction, tone, text, magnitude, label }, the same text and spoken sentence the component renders, for chart summaries and exports.

Exported from @rookcom/monarch-react/charts.

Generated from the TypeScript declarations of packages/react/src/components/charts/delta-indicator.

Properties

With format="percent" (the default) value is a ratio: 0.12 is 12%. Pass current and previous to have the change computed instead.

DeltaIndicator

A change between two periods: direction arrow, signed value and an optional comparison. Colour follows `goodDirection`, so a fall in costs is green; the arrow, sign and spoken "up 12% vs last month, better" carry the meaning without colour.

PropTypeDescription
appearance"pill" | "plain"`plain` (default) is inline text; `pill` puts the change in a tinted chip.
classNamestring
comparisonReactNodeThe comparison period after the change, e.g. "vs last month". Shown muted and spoken.
currencystringISO 4217 code for `format="currency"`, e.g. `USD`. Required in that format.
currentnumber | nullThis period's value; with `previous`, the change is computed.
flatThresholdnumberChanges whose size is at or below this count as flat. Default 0.
formatDeltaFormatDefault `percent`.
formatOptionsIntl.NumberFormatOptionsExtra `Intl.NumberFormat` options, e.g. `{ maximumFractionDigits: 0 }`.
formatValue((magnitude: number) => string)Writes the size of the change yourself (no sign); replaces `format`, `unit` and `formatOptions`.
goodDirectionDeltaGoodDirectionWhich direction is an improvement. Default `up`.
hideIconbooleanHides the direction arrow. The sign and the spoken direction remain.
idstring
labelsPartial<DeltaLabels>Words to show and speak; merged over the English defaults.
localestringBCP 47 locale. Default: the runtime locale.
previousnumber | nullThe previous period's value. With `format="percent"` the change is `(current − previous) / |previous|`, and a `previous` of 0 has no baseline, so it shows `labels.noData`. Otherwise the change is `current − previous`.
size"sm" | "md"`sm` (default) for card footers, `md` next to body text.
unitstringUnit written after a `number` change, e.g. `pt` or `ms`.
valuenumber | nullThe change itself. With `format="percent"` it is a ratio (0.12 is 12%). `null` means there is nothing to compare with. Takes precedence over `current` and `previous`.

Variants

PropValuesDescription
format'percent''number''currency'percent (default) writes a ratio as a percentage; number with an optional unit (pt, ms); currency through Money with currency.
goodDirection'up''down''neither'Which direction is an improvement. Default up. neither keeps the change neutral grey.
appearance'plain''pill'pill puts the arrow and value in a tinted chip (data-appearance).
size'sm''md'sm (default) for card footers and tables, md beside body text.

States

StateExposed asBehaviour
Up / downdata-direction="up|down"Arrow, signed value, visually hidden direction word and "better" or "worse".
Better / worse / neutraldata-tone="positive|negative|neutral"Derived from the direction and goodDirection.
Flatdata-direction="flat"Zero, within flatThreshold, or rounding to zero: a dash and "No change", neutral.
No datadata-emptyvalue null or not finite, current or previous missing, or a previous of 0 for a percentage: "No earlier data".

Interaction behaviour

  • None. DeltaIndicator is read-only text.

Keyboard support

Not interactive, so there is no keyboard behaviour.

Accessibility

Role
none (inline text)
Accessible name
The visually hidden sentence, e.g. "up 12% vs last month, better".
  • The arrow and the signed value are aria-hidden; a visually hidden "up 12%" or "down 8%" is read instead, so screen readers never say "plus" or skip a glyph.
  • The comparison is real text, read after the change, followed by a hidden "better" or "worse" when a direction is better.
  • Every word is replaceable through labels for translation.
  • In forced-colours mode the pill keeps a border; the arrow and sign remain.

Responsive behaviour

  • The change never wraps; the comparison may wrap onto the next line in narrow cells.

Theme support

  • Better uses --mn-color-success-strong, worse --mn-color-danger-strong, neutral --mn-color-text-muted; all meet AA text contrast in light, dark and high-contrast themes.
  • The pill tint is the matching -subtle token.

Do and don't

Do

  • Set goodDirection="down" for costs, latency, churn, bounce rate and rank positions.
  • Pass the comparison period ("vs last month") so the change is never ambiguous.
  • Use formatDelta for chart summaries so the words match the indicator.

Don't

  • Do not compute a percentage against a zero baseline; let DeltaIndicator show "No earlier data".
  • Do not invent a change when the product has no previous value: pass null.
  • Do not use a status colour on its own to show direction.
  • StatCard: A KPI tile that shows a DeltaIndicator through change.
  • Money: Formats currency changes.
  • Sparkline: A trend over many points rather than one change.
  • StatusBadge: A state rather than a change.

Dependencies

KindDepends on
npm packagesreact
Monarch componentsMoney, VisuallyHidden

Testing coverage

  • Signed percentage with spoken direction, comparison and quality; arrow hidden.
  • goodDirection down (costs) and neither; computed percentage and absolute changes with a unit.
  • Currency through Money and a custom formatter.
  • Flat for zero, inside the dead band and when rounding to zero.
  • No-data label for null, NaN, missing or zero baselines.
  • Translated labels and locale; pill, size, hideIcon; ref forwarding; formatDelta output.
CheckCovered
Axe in jsdomYes
Server renderingYes
Browser suitesVisual baselines: /__gallery/delta-indicator; Cross-browser axe: /components/delta-indicator

Tests: packages/react/src/components/charts/delta-indicator