demo D125
Presentation mode
Scale the whole grid up for a room, then come back
grid.presentation.start() · nudge() · stop()
The configuration
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.27.0/lattice-grid.min.css">
<div id="app"></div>
<script type="module">
import React from 'https://esm.sh/react@18';
import { createRoot } from 'https://esm.sh/react-dom@18/client';
import { createGrid } from 'https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.27.0/lattice-grid.esm.min.js';
import createLatticeGrid from 'https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.27.0/modules/react.esm.min.js';
const LatticeGrid = createLatticeGrid({ React, createGrid });
// Saved views are the slides the deck steps through.
const views = {
saved: [
{
id: 'prod-spend',
name: 'Production spend',
state: {
version: 1,
filters: { op: 'and', conditions: [{ col: 'environment', op: 'in', value: ['prod', 'prod-2', 'definitely-prod'] }] },
sort: [{ col: 'cost', dir: 'desc' }],
group: [],
},
},
{
id: 'biggest-movers',
name: 'Biggest movers',
state: { version: 1, filters: null, sort: [{ col: 'change', dir: 'desc' }], group: [] },
},
{
id: 'by-service',
name: 'By service',
state: { version: 1, filters: null, sort: [{ col: 'cost', dir: 'desc' }], group: ['service'] },
},
],
};
const columns = [
{ field: 'account', title: 'Account', filter: { type: 'set' } },
{ field: 'service', title: 'Service', filter: { type: 'set' } },
{ field: 'resource', title: 'Resource', layout: { flex: 1, min: 200, max: 320 } },
{ field: 'region', title: 'Region', filter: { type: 'set' } },
{ field: 'environment', title: 'Env', filter: { type: 'set' },
cell: { decoration: 'pill', variant: { map: {
prod: 'danger', 'prod-2': 'danger', 'definitely-prod': 'danger',
staging: 'warning', untagged: 'warning', test: 'info',
dev: 'success', 'not-prod': 'neutral',
} } } },
{ field: 'change', title: 'Change', type: 'number',
layout: { width: 140, min: 140 }, format: { style: 'percent', decimals: 1 } },
{ field: 'cost', title: 'Monthly cost', type: 'number', layout: { width: 170 },
format: { style: 'currency', currency: 'USD', decimals: 2 }, total: 'sum' },
];
const rows = [/* cloud cost rows */];
function App() {
const gridRef = React.useRef(null);
// Presentation is an API rather than a config key, and it takes over the
// viewport, so drive it from the live grid after it exists.
const present = () => gridRef.current.grid.presentation.start({ scale: 1.5 });
const presentDeck = () =>
gridRef.current.grid.presentation.start({ scale: 1.5, views: ['prod-spend', 'biggest-movers', 'by-service'] });
// A spotlight paints while presenting and dims every cell outside the
// Monthly cost column.
const spotlightCost = () => gridRef.current.grid.presentation.setSpotlight({ colIds: ['cost'] });
const stop = () => gridRef.current.grid.presentation.stop();
return (
<>
<div style={{ display: 'flex', gap: '8px', marginBottom: '12px' }}>
<button onClick={present}>Present</button>
<button onClick={presentDeck}>Present the views as slides</button>
<button onClick={spotlightCost}>Spotlight the cost column</button>
<button onClick={stop}>Stop</button>
</div>
<LatticeGrid
ref={gridRef}
rowKey="id"
selection="multiple"
views={views}
toolPanel={{ side: 'left', panels: ['columns', 'filters', 'views', 'quick'],
exportName: 'lattice-demo', actions: ['restore', 'maximise'] }}
columns={columns}
rows={rows}
style={{ height: '540px' }}
/>
</>
);
}
createRoot(document.getElementById('app')).render(<App />);
</script>
Scaling a grid up for a room, then handing control back
Presentation mode enlarges the whole grid for viewing at a distance, then returns it to its normal layout without losing the reader’s place. A developer reaches for it when a JavaScript data grid built for a desk gets walked into a meeting: a dashboard cast to a conference screen, a review of figures on a shared monitor, a status board glanced at from across a room. Rather than a separate zoomed view, Lattice Grid scales the existing rows and columns in place, so column widths, sort order, and any applied filters stay exactly as the presenter left them. The demo is driven through grid.presentation.start(), nudge(), and stop(): start switches to the enlarged layout, nudge steps the focus forward or back a row so a presenter can advance through figures from a clicker or the keyboard, and stop restores the working layout. Because the scaling changes font size and row height rather than re-rendering the data, the switch is immediate even on a grid holding tens of thousands of rows, and virtual scrolling continues to render only the rows in view, so a large table stays as responsive at presentation scale as at desk scale. Keyboard focus carries across the switch, so a screen reader user does not lose their position when the layout changes size.
How do I make a data grid readable from across a room?
Call grid.presentation.start() to switch the grid into an enlarged layout that keeps the current data, sort, and filters in place, then nudge() to step through rows without leaving the keyboard. grid.presentation.stop() returns the grid to its normal size. The scaling only changes row height and font size, so it works the same way regardless of how many rows the grid is holding.