Lattice Grid Buy a licence

blog

Lattice Grid 1.70: a lighter grid, and KPI tiles that know a dead feed

Four things in this release change what you can put on a screen. The rest you get for free.

A quarter less to download

The core bundle is now 2,363 KB, 655 KB over the wire, down from 3,203 KB and 745 KB. Every module bundle has slimmed with it. Your page sees the same API, the same config keys, the same data-* attributes, events and CSS class names, because none of those are touched; only the internals got tighter.

Source maps ship beside every bundle, so a stack trace from production points at a real line and a real name. And the build now keeps a record of every bundle’s size and holds the line release after release, so the grid you load next year is not quietly heavier than the one you load today.

On a dashboard people open on a phone or over a slow link, this is the release that makes the first paint feel quick.

A KPI tile that knows when a feed goes quiet

A wall of count tiles over a live feed, each graded good, warn or critical. One reads “0 critical alarms”. Good news, or a feed that stopped an hour ago?

Tell the tile how fresh its data has to be and it answers that question for you:

createKPI(el, {
  maxAge: 30_000,          // rows older than 30 s no longer count
  ageBy: 'observedAt',     // by the row's own clock; omit it to use arrival time
  tiles: [{ id: 'critical', label: 'Critical alarms', aggregation: 'count',
            thresholds: { warn: 1, critical: 5, direction: 'lowerIsBetter' } }],
});

When every row has aged out, the tile shows a dashed edge and “No recent data” rather than a green zero. When fresh rows arrive and none match, it shows a real zero, because that is what it is. A heading in a KPI tree counts a quiet leaf beneath it, so the summary at the top tells the truth about the tiles below.

maxAge and ageBy are the same two words a stream source already uses for its rolling window. If you have set one, you already know the other.

Column text only

headerControls: 'none' gives you a heading that shows the column title and nothing else, whatever the grid is doing. No hover controls, no sort or filter affordances, no sort arrow even when the column is sorted through the API. It is built for the wallboard nobody clicks on: a network operations centre, a factory floor, a trading screen on a monitor across the room.

{ field: 'severity', title: 'Severity', headerControls: 'none' }

The quieter settings you already have still apply: 'hidden' keeps a read-only sort badge for screens that are read up close, and 'none' drops even that.

An API reference you can navigate

The reference is now an index plus one page per module: grid, charts, data router, KPI, kanban, gantt, tabs, layout, AI, mock socket, adapters and types. Every type name in every table links to its definition, and 236 type aliases have an entry of their own. Density, ScrollbarMode, KpiStatus and the rest can be imported by name from the package’s entry points, so a typed wrapper is a one-line import.

It ships inside the package under docs/api/, and it is live on this site under /docs/api/.

Also in this release

  • The npm package now carries its CHANGELOG.md, so the release history is in node_modules beside the code.
  • The Python wrappers now track every grid release automatically: pip install lattice-grid-jupyter gets the current grid the day it ships. Datetime edits in a notebook round-trip to the DataFrame as UTC, to the millisecond.
  • A chart extension loaded ahead of the charts module tells you exactly what to load first.
  • A chart bound to a column that is not there says so and shows its empty state.
  • Repeated refusals are announced every time to screen-reader users, in the grid and in the Gantt.
  • Sixty more interface phrases come from the message catalogue, so every one of the twenty bundled locales covers them.
  • A filtered query against a large Parquet file shows its rows as soon as the page settles, with the exact total following a moment later.

One change to note

The default export is now frozen, matching the top-level export. A host that assigned to LatticeGrid.default.createGrid will see a refusal on the first call, and should wrap createGrid instead.

The full list is in the changelog.

Read next

  • A grid over DuckDB, in the browser

    Point Lattice Grid at a duckdb-wasm connection and it pushes filter, sort and paging down, and gets whole-dataset stats by pulling the set in or pushing the aggregation to DuckDB.

  • A grid that keeps up with the feed

    Rows arriving faster than anyone can read them, a grid that stays scrollable while they do, and a rate measured in your browser rather than ours.

  • Width is the harder problem

    Everybody demos a long grid. The one that hurts is the wide one, where the row you are reading loses its name somewhere around column nineteen.

All posts RSS