ibcs-react
Components

KpiCard

A headline figure (count-up animated) with impact-coloured deltas vs PY/PL and an optional sparkline.

A single headline number with one or more IBCS impact-coloured deltas - the colour follows favorability, not the sign - and an optional sparkline under the figure. Built to drop into a report grid as a kpi block.

When to use

A single KPI in a dashboard strip - revenue, margin, headcount - with its variance and trend at a glance.

Example

Revenue
30.1M+4.5M+17.6%vs PY
+1.6M+5.6%vs PL
import { KpiCard } from "ibcs-react";

<KpiCard
  label="Revenue"
  values={{ AC: 30.1e6, PY: 25.6e6, PL: 28.5e6 }}
  comparisons={["PY", "PL"]}
  sparkline={[2.3e6, 2.45e6, 2.6e6, 2.9e6]}
/>;

More examples

A cost KPI (higherIsBetter = false)

For costs, an increase is unfavorable. Setting higherIsBetter={false} flips the impact colouring, so the +1.3M rise reads red even though the number went up.

Revenue
30.1M+4.5M+17.6%vs PY
Operating cost
9.7M+1.3M+15.5%vs PY
// Revenue up -> green (favorable)
<KpiCard label="Revenue" values={{ AC: 30.1e6, PY: 25.6e6 }} comparisons={["PY"]} />

// Cost up -> red, because higher is worse
<KpiCard
  label="Operating cost"
  values={{ AC: 9.7e6, PY: 8.4e6 }}
  comparisons={["PY"]}
  higherIsBetter={false}
/>

Units live in format

There is no unit prop. The unit is part of format: currency for a leading symbol ({ currency: "€" } renders €30.1M), suffix for a trailing one ({ suffix: "%" } renders 18.4%). The card states the unit once, muted, beside the headline instead of repeating it on every delta.

Revenue
€30.1M+4.5M+17.6%vs PY
Gross margin
18.4%+1.3+7.6%vs PY
<KpiCard label="Revenue" values={{ AC: 30.1e6, PY: 25.6e6 }} format={{ currency: "€" }} />
<KpiCard
  label="Gross margin"
  values={{ AC: 18.4, PY: 17.1 }}
  format={{ suffix: "%", compact: false, decimals: 1 }}
/>

Set animate={false} to render the headline outright - no frame loop, no re-renders - which is what you want in tests, print and SSR-heavy pages. Users with prefers-reduced-motion set never see the count-up either way: the default consults the OS preference and renders the final value immediately, and SSR always emits the finished figure.

Ratio measures: percentage-point deltas

A percentage MEASURE - a margin, a rate, a share - moves in percentage points. Declare it with unit="ratio" and the delta renders as +0.6pp, while the relative delta is dropped: "+0.9%" beside "18.4%" invites reading a relative change as points, the exact confusion ISO 24896 separates the two notations to prevent.

EBIT margin
18.4%+1.3ppvs PY
Churn rate
3.1%-0.3ppvs PY
<KpiCard
  label="EBIT margin"
  values={{ AC: 18.4, PY: 17.1 }}
  unit="ratio" // deltas in percentage points: +1.3pp, no relative %
  format={{ suffix: "%", compact: false, decimals: 1 }}
/>

The linter pairs with it: checkIbcs emits a ratio-units info for a KPI formatted with suffix: "%" that has not been declared a ratio.

Props

Prop

Type

ibcs-react is an independent open-source library and is not affiliated with, certified by, or endorsed by the IBCS Association or ISO. It follows the IBCS® notation rules (the basis of ISO 24896); IBCS® is a registered trademark of the IBCS Association.

On this page