ibcs-react

IBCS & ISO 24896

The notation rules baked into every component - scenario fills, favorability colouring, signed values, zero baselines and structured titles.

This library implements the IBCS® notation - the notation described by ISO 24896:2026, "Notation for business reporting". The rules below are baked into every component, so reports come out consistent without a house-style debate on every chart.

Scenario fills

Scenarios are distinguished by fill, not colour - so a report stays legible in greyscale and never confuses "what happened" with "what we planned". The four scenario keys render as:

AC · Actual
solid, dark - this is real
PY · Previous year
solid grey - the past
PL · Plan / budget
outline frame - not real yet
FC · Forecast
hatched - expected

Actuals are solid, previous year is solid grey, plan is an outline (it hasn't happened yet) and forecast is hatched (expected). You see the same grammar in TrendChart, where actual columns are solid and the forecast tail is hatched.

Plan / budget (PL) is the easy one to miss - a deliberately hollow outline. Below, solid actuals are compared against plan: the thin rectangular frames behind each quarter are the PL columns, and the variance panel reads AC vs PL. Switch the toggle to compare against previous year instead - same data, a different yardstick.

Compare actuals to:
Revenue - Actual vs Plan€6.8MQ1€7.3MQ2€7.6MQ3€8.4MQ4+€300K+€300K+€200K+€800K
Revenue - Actual vs Plan - data table
ACPLΔPLΔPL%
Q1€6.8M€6.5M+€300K+4.6%
Q2€7.3M€7M+€300K+4.3%
Q3€7.6M€7.4M+€200K+2.7%
Q4€8.4M€7.6M+€800K+10.5%

Variance is coloured by impact, not sign

A deviation is green when it is good for the business and red when it is bad - regardless of whether the number went up or down. Revenue up is green; cost up is red. Lines and data carry higherIsBetter (set it to false on cost, expense and tax measures) so the colour follows favorability, not the arithmetic sign.

Revenue
€30.1M+4.5M+17.6%vs PY

Up +4.5M - favorable, so green.

Operating cost
€9.7M+1.3M+15.5%vs PY

Also up - but cost up is unfavorable, so red.

<KpiCard label="Revenue" values={{ AC: 30.1e6, PY: 25.6e6 }} comparisons={["PY"]} />

// Same arithmetic, opposite meaning:
<KpiCard
  label="Operating cost"
  values={{ AC: 9.7e6, PY: 8.4e6 }}
  comparisons={["PY"]}
  higherIsBetter={false}
/>

Signed values

Variances always show their sign - +4.5M, −1.3M, +17.6%. The sign tells the direction of change; the colour tells whether that change is good. The two are independent on purpose, which is why a +1.3M cost overrun reads red.

Absolute deviations are bars, relative ones are pins

Absolute deviations (currency units) are drawn as bars - they share the value axis, so magnitudes are comparable. Relative deviations (percent) are drawn as pins (a lollipop: line plus dot) on their own percent scale, so a small absolute swing on a small base doesn't masquerade as a big bar.

Absolute · bars6.8 mQ17.3 mQ27.6 mQ38.4 mQ4+0.7 m+0.9 m+0.9 m+2 m
Absolute · bars - data table
ACPYΔPYΔPY%
Q16.8 m6.1 m+0.7 m+11.5%
Q27.3 m6.4 m+0.9 m+14.1%
Q37.6 m6.7 m+0.9 m+13.4%
Q48.4 m6.4 m+2 m+31.3%
Relative · pins6.8 mQ17.3 mQ27.6 mQ38.4 mQ4+11.5%+14.1%+13.4%+31.3%
Relative · pins - data table
ACPYΔPYΔPY%
Q16.8 m6.1 m+0.7 m+11.5%
Q27.3 m6.4 m+0.9 m+14.1%
Q37.6 m6.7 m+0.9 m+13.4%
Q48.4 m6.4 m+2 m+31.3%
<VarianceColumnChart data={quarterly} comparison="PY" variance="abs" mark="bar" />
<VarianceColumnChart data={quarterly} comparison="PY" variance="pct" mark="pin" />

StatementTable follows the same convention out of the box: its default variance panels are an absolute bar column and a percent pin column against PY.

Zero-baseline axes

Bar and column charts always start at zero - never a truncated axis - so the length of a bar is proportional to its value and visual comparisons aren't exaggerated. The waterfall lane in StatementTable shares one zero baseline across all rows, and steps that cross zero render to the left of it.

Who / What / When titles, message kept separate

A report title answers Who (entity or unit), What (measure and unit, e.g. "Revenue - € thousands") and When (period and comparison). The interpretive key message ("Up 17.5% on prior year") is kept separate from the descriptive title - Report takes a structured title and a message field for exactly this reason.

Acme Corporation
Revenue - € thousands
FY 2026 vs PY

Key message · Up 17.5% on prior year, led by Service revenue.

In short

Fills carry the scenario, colour carries favorability, length carries magnitude from zero, and the title states facts while the message states the point.

  • Conformance - lint a config against the IBCS notation rules the library implements.
  • Theming - change the palette without breaking the grammar.
  • Data model - the shapes that carry higherIsBetter and the scenario values.
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