ibcs-react
Components

StatementTable

The IBCS table with measure rows and integrated waterfalls (templates T03/T04) - a P&L or balance sheet with embedded variance bars and pins.

A financial statement rendered as one integrated view: the label column, an embedded waterfall lane for the actual scenario, and right-hand variance panels against each comparison base. Deviation and structure are read in a single pass, without leaving the table.

When to use

An income statement, a balance sheet, or any build-up of figures to subtotals - lines that add, subtract and resolve into results. For a cross-entity comparison (revenue by region, headcount by team) where rows do not build up to a total, use DataTable instead.

Example

 PYACΔPYΔPY%
Product revenue16.1M17.2M+1.1M+6.8
Service and other revenue9.5M12.9M+3.4M+35.8
=Revenue25.6M30.1M+4.5M+17.6
−Product cost3.1M3.5M+400K+12.9
−Service and other costs5.3M6.2M+900K+17.0
=Gross margin17.2M20.4M+3.2M+18.6
−Research and development3.5M3.9M+400K+11.4
−Sales and marketing4.3M4.8M+500K+11.6
−General and administrative1.4M1.3M-100K-7.1
=Operating income8M10.4M+2.4M+30.0
Other income, net276K301K+25K+9.1
=Income before income taxes8.3M10.7M+2.4M+29.3
−Provision for income taxes195K1.8M+1.6M+823.1
=Net income8.1M8.9M+820K+10.1
import { StatementTable } from "ibcs-react";

<StatementTable
  lines={statement}
  varianceColumns={[
    { base: "PY", mode: "abs", mark: "bar" },
    { base: "PY", mode: "pct", mark: "pin" },
  ]}
  mark="bar"
  format={{ compact: true, decimals: 1 }}
/>;

Pin mark and relative variance

Draw the waterfall lane as pins and add a percent (ΔPY%) panel - pins keep small bases honest against the absolute bars.

 PYACΔPYΔPY%
Product revenue16.1M17.2M+1.1M+6.8
Service and other revenue9.5M12.9M+3.4M+35.8
=Revenue25.6M30.1M+4.5M+17.6
−Product cost3.1M3.5M+400K+12.9
−Service and other costs5.3M6.2M+900K+17.0
=Gross margin17.2M20.4M+3.2M+18.6
−Research and development3.5M3.9M+400K+11.4
−Sales and marketing4.3M4.8M+500K+11.6
−General and administrative1.4M1.3M-100K-7.1
=Operating income8M10.4M+2.4M+30.0
Other income, net276K301K+25K+9.1
=Income before income taxes8.3M10.7M+2.4M+29.3
−Provision for income taxes195K1.8M+1.6M+823.1
=Net income8.1M8.9M+820K+10.1
<StatementTable
  lines={statement}
  mark="pin"
  varianceColumns={[
    { base: "PY", mode: "abs", mark: "bar" },
    { base: "PY", mode: "pct", mark: "pin" },
  ]}
  format={{ compact: true, decimals: 1 }}
/>

Stock mode - a balance sheet

The same component renders point-in-time levels instead of a flow waterfall: each line is an absolute bar, with no running total. Liability lines carry higherIsBetter: false, so a rise in debt reads as unfavorable. Groups with children collapse and expand.

 PYACΔPYΔPY%
Current assets14.8M16.7M+1.9M+12.8
Cash and equivalents6.5M8.2M+1.7M+26.2
Accounts receivable4.9M5.4M+500K+10.2
Inventory3.4M3.1M-300K-8.8
Non-current assets19.2M20.3M+1.1M+5.7
Property, plant & equipment11.2M12M+800K+7.1
Goodwill & intangibles6.3M6.3M00.0
Other non-current assets1.7M2M+300K+17.6
=Total assets34M37M+3M+8.8
Liabilities17.3M17M-300K-1.7
Accounts payable3.6M4.1M+500K+13.9
Short-term debt3M2.5M-500K-16.7
Long-term debt9.5M9M-500K-5.3
Deferred tax & other1.2M1.4M+200K+16.7
Shareholders' equity16.7M20M+3.3M+19.8
Share capital5M5M00.0
Retained earnings11.7M15M+3.3M+28.2
=Total liabilities & equity34M37M+3M+8.8
<StatementTable
  lines={balanceSheet} // ending balances, not period movements
  mode="stock" // absolute levels, not a waterfall
  format={{ compact: true, decimals: 1 }}
/>

Collapsed groups: controlled or uncontrolled

Grouped statements track a collapsed set of group ids. Both modes are supported, and mixing them is the usual mistake:

  • Uncontrolled - pass defaultCollapsed (a seed applied on mount, which overrides each line's own defaultCollapsed flag) and let the table own the state. onCollapsedChange still fires, as a plain observer.
  • Controlled - pass collapsed (a ReadonlySet<string> or a string array). The table then renders exactly that set and never mutates it; every toggle, and the Expand all / Collapse all buttons, report the next ids through onCollapsedChange for you to apply - useful for URL sync, persistence, or keeping two tables in step.
const [collapsed, setCollapsed] = useState<string[]>(["noncurrent-assets"]);

<StatementTable
  lines={balanceSheet}
  mode="stock"
  expandControls
  collapsed={collapsed}
  onCollapsedChange={setCollapsed}
/>;

Set maxHeight for long consolidations: the body scrolls under a sticky header and row virtualization turns on by default (virtualize).

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