react data grid · kpi tiles
React Grid: KPI Tiles
A row of live figures beside the grid, reading the same rows it holds: a running total, an average measured against a baseline, a count that changes colour past a threshold, and a sparkline, all moving together as the data changes.
Also in: Angular
Install and import
npm install @toclocoinc/lattice-grid
# free on localhost; a production domain needs a licence key (see /pricing/)
The files
lattice.ts
// lattice.ts
import React from 'react';
import { createGrid } from '@toclocoinc/lattice-grid';
import '@toclocoinc/lattice-grid/css';
import { createKPI } from '@toclocoinc/lattice-grid/modules/kpi';
import { createLatticeReact } from '@toclocoinc/lattice-grid/modules/react';
export const { LatticeGrid, LatticeKPI } = createLatticeReact({ React, createGrid, createKPI });
Pipeline.tsx
// Pipeline.tsx
import React from 'react';
import { createRoot } from 'react-dom/client';
import { LatticeGrid, LatticeKPI } from './lattice';
const MONEY = { style: 'currency', currency: 'USD', decimals: 0 };
const OPEN = { warn: 14, critical: 22, direction: 'lowerIsBetter' };
const columns = [
{ field: 'id', title: 'Ref', layout: { width: 96, pin: 'start' } },
{ field: 'region', title: 'Region', filter: { type: 'set' } },
{ field: 'stage', title: 'Stage', filter: { type: 'set' } },
{ field: 'value', title: 'Value', type: 'number', format: MONEY, total: 'sum' },
];
const rows = [/* deal records: id, region, stage, value */];
// Each tile is an aggregate over the same rows: a running total, an average
// against a baseline, a count with a good/warn/critical band, and a
// sparkline over the biggest deal.
const tiles = [
{ id: 'revenue', label: 'Pipeline value', aggregation: 'sum', field: 'value', format: 'currency' },
{ id: 'avg', label: 'Average deal vs $12k', aggregation: 'avg', field: 'value', format: { type: 'currency', decimals: 0 }, baseline: 12000 },
{ id: 'open', label: 'Still open', aggregation: 'count', filter: (r: any) => r.stage !== 'won', thresholds: OPEN },
{ id: 'biggest', label: 'Biggest deal', aggregation: 'max', field: 'value', format: 'currency', sparkline: 'value' },
];
function Pipeline() {
const [grid, setGrid] = React.useState<any>(null);
// The KPI panel takes the live grid as a prop, once the grid reports it is
// ready, and reads the same rows a chart or a board would.
return (
<>
{grid && <LatticeKPI grid={grid} columns={4} tiles={tiles} style={{ marginBottom: 12 }} />}
<LatticeGrid rowKey="id" columns={columns} rows={rows} onGridReady={setGrid} style={{ height: '320px' }} />
</>
);
}
createRoot(document.getElementById('pipeline')!).render(<Pipeline />);
See it running
Working in React
createLatticeReact, not createLatticeGrid alone. A KPI panel is a second
component, built from the same call as the grid so both share one React and one
createGrid. Import only createKPI alongside it and nothing else about a
board, a chart or the Gantt is pulled in.
The panel waits for its grid. A template ref cannot tell a sibling the grid has
arrived, because writing to a ref re-renders nobody; onGridReady is the documented way
a KPI panel (or a chart) learns which instance to read, which is why <LatticeKPI>
is only rendered once grid is set.
Tiles update on a grid event, not a React one. A tile recomputes when the grid's own rows or filter changes, so filtering the grid moves every tile automatically, with no state of your own to keep in sync.
Related
Read the docs React data grid overview Free on localhost. See pricing.