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:
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.
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.
Up +4.5M - favorable, so green.
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.
<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.
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
higherIsBetterand the scenario values.