Lattice Grid Buy a licence

blog

List view, tree and card view on a data grid, 1.105

Building…
Loading a live grid…

A business app rarely stops at a grid. The same page has a list of tickets, a tree of folders and a wall of cards, and each one usually arrives from a different library with its own data model, its own idea of selection and its own keyboard behaviour. Then someone asks for dark mode, and a theme change is four jobs instead of one.

Releases 1.104 and 1.105 close that gap. A list view, a tree and a data view of cards are now built on the grid itself, and in 1.105 all three read the same theme as the grid. The example above is one page with all four. Pick a preset, flip light and dark, and watch every view restyle together.

Why building the views on the grid matters

A list that is its own library has its own rows, its own selection and its own scrolling. Here the list view, the tree and the data view are the grid underneath, with a template drawing each item. That is what they inherit:

  • One data API. Add, update, remove and serialise work the same way on a list, a tree and a card view, and what you read back always matches what is on screen.
  • One selection model. A click, a keypress and a call from your code all agree, in single or multiple mode.
  • Keyboard and accessibility. Arrow keys move through rows, nodes and cards, and the accessibility semantics come from the grid underneath.
  • Virtual scrolling. Only the rows or cards in view are drawn, so a long list is not a slow one.
  • Drag between views. Drag a row from the list view into the data view and back. The tree drags a node under another, and a veto in beforeDrop leaves both sides as they were.

Try it in the example. Select two rows in the list view and drag them over to the cards.

import { createList } from '@toclocoinc/lattice-grid/modules/listview';
import { createDataView } from '@toclocoinc/lattice-grid/modules/dataview';

const list = createList(listEl, { createGrid, data, template, selection: 'multi', dragMode: 'both' });
const cards = createDataView(cardsEl, { data, template: cardTemplate, selection: 'multi', dragMode: 'both' });

One theme for the grid and the views

In 1.105 rows, cards, hover, selection, focus rings, drop markers and empty states draw from the same tokens as the grid: colours, density, radius, focus ring, selection and drop indicator. There is no per-view CSS to write. Dark mode and each of the four design-system presets apply to the three views exactly as they do to the grid, and a theme change while the page is open restyles them at once, with no reload. The app shell header follows the theme as well.

The switcher above never rebuilds the views. It swaps the preset stylesheet and sets data-theme, and the four views change in place. The full list of what each preset sets is on the presets page.

A rail that shows when the rows are filtered

A filter that narrows the rows is easy to forget about. You open a grid, see forty rows where you expected four hundred, and nobody told you why. In 1.105 the side rail marks it: the Filters tab shows a small dot while any filter narrows the rows, however it was set, and the quick search tab shows one while a quick search is narrowing them. The count of filtered columns is in the button’s accessible name, and the dot clears as soon as the filter does.

Use the buttons above the grid, or the Filters panel in the rail, then look at the tab. The readout shows the name a screen reader gets.

Building…
Loading a live grid…

Upgrading

From 1.103, the list view, tree and data view are new opt-in modules: import the ones you want, alongside the grid. From 1.104, there is nothing to change. Theming is on by default.

The changelog has the full list of changes, and the grid engine page covers the core the views are built on.

Read next

All posts RSS