Lattice Grid Buy a licence

demo D130

Header context menu

Right-click a heading. The menu, not the rendering

header:contextmenu

Building…
Loading a live grid…

The configuration

<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@toclocoinc/lattice-grid@1.27.0/lattice-grid.min.css">

<div id="grid"></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 });

  // The header menu opens on right-click. Team is marked lockVisible, so it
  // stays out of the hide action the menu offers.
  const columns = [
    { field: 'service', title: 'Service', layout: { pin: 'start', width: 160 } },
    { field: 'team', title: 'Team', layout: { width: 130, lockVisible: true }, filter: { type: 'set' } },
    { field: 'owner', title: 'Owner', filter: { type: 'set' } },
    { field: 'headcount', title: 'Headcount', type: 'number', total: 'sum' },
    { field: 'monthlyCost', title: 'Monthly cost', type: 'number',
      format: { style: 'currency', currency: 'USD' }, total: 'sum' },
    { field: 'budget', title: 'Budget', type: 'number',
      format: { style: 'currency', currency: 'USD' }, total: 'sum' },
  ];

  const rows = [/* service records */];

  function App() {
    return (
      <LatticeGrid
        rowKey="id"
        selection="multiple"
        toolPanel={{ side: 'left', panels: ['columns', 'filters', 'views', 'quick'],
          actions: ['undo', 'redo', 'export', 'restore', 'maximise'], exportName: 'lattice-demo' }}
        columns={columns}
        rows={rows}
        style={{ height: '540px' }}
      />
    );
  }

  createRoot(document.getElementById('grid')).render(<App />);
</script>

Right-clicking a column heading for a menu of column-level actions

A context menu attached to the header row gives a user a place to act on a column as a whole, separate from the cell context menu that acts on a single value. Sorting, pinning, hiding, and grouping are the operations that belong here: they change the shape of the table rather than the content of a record, and putting them behind a right-click keeps the header free of icon clutter. Any JavaScript data grid with a dense set of columns benefits from this split, since a toolbar button for every column operation would not fit above a wide table, while a menu scoped to the column under the pointer scales to however many columns are configured.

Lattice Grid exposes the interaction through the header:contextmenu event, fired with the column definition and the triggering event, so a host application can build its own menu contents, filter which actions appear per column, or suppress the menu on columns marked non-configurable. The default menu closes on outside click, on Escape, and after an item is chosen, returning focus to the header cell that opened it. It is reachable without a mouse: the context-menu key and Shift+F10 open it on a focused header, and the menu itself is a role="menu" with arrow-key navigation between items.

How do you open a column’s context menu without a mouse?

Focus the column header with Tab or the arrow keys, then press the keyboard context-menu key or Shift+F10. Lattice Grid opens the same menu a right-click would, positioned against the focused header cell, with arrow-key navigation between items and Escape to dismiss it.