DataTable
The IBCS table with hierarchical rows and variance columns (template T01) - rows are entities, columns are values, embedded variances and sparklines.
The general comparison table: rows are entities (regions, teams, products), columns are measures. A column is a plain value, a variance drawn as an embedded bar or pin, or a sparkline - so magnitude, deviation and trend sit side by side in one grid.
When to use
A cross-entity comparison: revenue by region, headcount by team, cost by category. Use StatementTable instead when rows build up to subtotals (a P&L or a balance sheet), and ComparisonTable when the row labels should sit in the centre, flanked by two period groups.
Example
Six regions and two measures (revenue and operating income), each with an
absolute ΔPY bar; revenue also gets a relative-variance pin and a sparkline.
Header clicks re-sort, and showTotals appends a summed row.
| Trend | ||||||
|---|---|---|---|---|---|---|
| North America | 11.2M | 2M | ||||
| Europe | 8.6M | 1.7M | ||||
| Asia Pacific | 5.1M | 1.1M | ||||
| Latin America | 2.1M | 340K | ||||
| Middle East & Africa | 1.1M | 180K | ||||
| Other | 900K | 80K | ||||
| Total | 29M | 5.4M |
import { DataTable } from "ibcs-react";
<DataTable
columns={[
{ key: "rev", label: "Revenue", kind: "value", scenario: "AC" },
{
key: "rev_d",
label: "ΔPY",
kind: "variance",
measure: "rev",
base: "PY",
mode: "abs",
mark: "bar",
},
{
key: "rev_p",
label: "ΔPY %",
kind: "variance",
measure: "rev",
base: "PY",
mode: "pct",
mark: "pin",
},
{ key: "trend", label: "Trend", kind: "sparkline", measure: "rev" },
{ key: "oi", label: "Op. income", kind: "value", scenario: "AC" },
{
key: "oi_d",
label: "ΔPY",
kind: "variance",
measure: "oi",
base: "PY",
mode: "abs",
mark: "bar",
},
]}
rows={performanceByRegion} // { id, label, values: { rev: { AC, PY }, oi: { AC, PY } }, spark: { rev } }
showTotals
defaultSort={{ key: "rev", dir: "desc" }}
/>;Rows may nest through children: a parent renders as a bold group that sums
its children and collapses on click.
Sorting: controlled or uncontrolled
Clicking a header cycles the sort: descending, then ascending, then off.
- Uncontrolled - seed the initial order with
defaultSort({ key, dir }, ornullfor unsorted) and let the table own it.onSortChangestill fires as an observer. - Controlled - pass
sort(ornull) plusonSortChange. The table renders exactly that sort and never mutates it; each header activation reports the next sort -nullwhen the cycle clears it - for you to apply.
The collapsed groups follow the same convention: defaultCollapsed is the
uncontrolled seed, collapsed (a ReadonlySet<string> or string array) plus
onCollapsedChange is the controlled pair. Once collapsed is provided, the
matching default* prop is ignored.
const [sort, setSort] = useState<DataTableSort | null>({ key: "rev", dir: "desc" });
const [collapsed, setCollapsed] = useState<string[]>([]);
<DataTable
columns={columns}
rows={rows}
sort={sort}
onSortChange={setSort}
collapsed={collapsed}
onCollapsedChange={setCollapsed}
/>;Props
Prop
Type
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.
ComparisonTable
The IBCS table with hierarchical rows and integrated bar charts (templates T01/T02) - two period column groups either side of the centre row labels.