Report
Render a whole report from a JSON ReportConfig - a responsive grid of KPI, chart, statement, table and text blocks.
One component renders an entire page from a serializable ReportConfig: a
structured Who / What / When title, a key message, and a responsive grid of
blocks. Each block names its type, its span on the grid, and a config object -
so a report is data you can store, version and generate, not hand-written JSX.
When to use
Assembling a dynamic report from cards and blocks that are authored, stored or produced elsewhere - a report builder, a saved layout, a server-generated dashboard. When the layout is fixed and hand-written, compose the individual components directly instead.
Example
Up 17.5% on prior year.
import { Report } from "ibcs-react";
const config = {
title: { who: "Acme", what: "Revenue - EUR thousands", when: "FY 2026 vs PY" },
message: "Up 17.5% on prior year.",
columns: 12,
blocks: [
{
id: "k1",
type: "kpi",
span: 4,
config: { label: "Revenue", values: { AC: 30.1e6, PY: 25.6e6 } },
},
{ id: "c1", type: "chart", span: 8, config: { type: "trend", data: months } },
{ id: "s1", type: "statement", span: 12, config: { lines: statement } },
],
};
<Report config={config} />;Blocks
Every block carries an id, an optional span (columns of the grid, which
defaults per type), an optional structured title and an optional message -
the interpretive one-liner, kept separate from the neutral title. The type
then selects the renderer and the shape of config:
type | Renders | config |
|---|---|---|
kpi | KpiCard | KpiConfig - label, scenario values, comparisons, format, optional sparkline |
chart | ConfiguredChart | ChartConfig - a type plus that chart's data and options |
statement | StatementTable | StatementBlockConfig - lines, mode, variance columns, format |
table | DataTable | TableBlockConfig - columns, rows, totals, initial sort, format |
text | Prose | the block's own title, message and body (blank lines split paragraphs) |
On screens narrower than 760px the grid collapses to a single column, so every
block spans the full width; collapseBelow moves that breakpoint or, with
false, removes it. It is a screen rule only - when printed (or rendered to
PDF) the authored spans hold whatever the paper width, so an A4 page does not
turn a 12-column report into a stack.
How blocks are framed is the theme's card tokens: the default is a hairline
card, flatCard is whitespace alone - the IBCS SIMPLIFY look and what paper
wants. See Theming. For the CSS a theme
cannot express, the parts have stable selectors: .ibcs-report (root, before
your className), .ibcs-report-grid, and one .ibcs-report-block per block
carrying data-block-type and data-block-id.
import { Report, flatCard } from "ibcs-react";
// print / PDF: no frames, spans kept
<Report config={report} tokens={{ card: flatCard }} collapseBelow={false} />;Chart blocks go through ConfiguredChart, which validates the config and
renders a readable message instead of throwing when it is invalid - 11 of the
23 chart components are reachable this way. Use validateReportConfig to check
an untrusted (JSON-authored) report before rendering it.
import { ConfiguredChart, validateReportConfig } from "ibcs-react";
<ConfiguredChart config={{ type: "trend", data: months, width: 620, height: 300 }} />;
const result = validateReportConfig(JSON.parse(saved));
if (!result.ok) console.warn(result.error);Blocks that measure the same thing can be tagged with the same
sharedScaleGroup and resolved with sharedScales (or the standalone
resolveSharedScales). Today this is advisory: the resolved domain is
published on each chart block's wrapper as data-shared-scale-group and
data-shared-scale-domain, rather than forced onto the rendered axis.
Props
Prop
Type
ConfiguredChart
Prop
Type