Foundation component ยท Data editing
Data Grid
An editable grid for records, cell ranges, and keyboard-driven work.
Live playground
| 1 | Quantum Manufacturing | Berlin, Germany | Veronica Han | 10 | quantum.com | |
| 2 | Synergy Solutions | Cape Town, SA | Min-ji Kim | 76 | synergy.com | |
| 3 | Apex Networks | Zurich, Switzerland | Lars Jensen | 160 | apex.com | |
| 4 | Fusion Ventures | Cairo, Egypt | Lily Sinh Katty | 320 | fusion.com | |
| 5 | Vertex Bio | Dublin, Ireland | Wei Chen | 810 | vertex.com | |
| 6 | Cortex AI | Bogotรก, Colombia | Rachel Green | 1200 | cortex.com | |
| 7 | Pinnacle Energy | Manila, Philippines | Sarah Jenkins | 6 | pinnacle.com | |
| 8 | Horizon Finance | Chicago, USA | Michael Chang | 85 | horizon.com |
Double-click a cell to edit. Drag across cells to select a range.
When to use it
- Use Data Grid when records are edited in place or users need to select a two-dimensional range.
- Use Data Table for read-only comparison and summaries. Its native table structure needs less interaction machinery.
- Show the shared Selection Toolbar for row selection, with batch actions supplied by the consumer. Keep cell-range selection separate from row actions.
- The headless
useDataGridprimitive owns selection, sorting, sizing, and atomic edit transactions. The styled component supplies Lenso cell geometry and interaction surfaces. - Use the same quiet header, row height, typography, and selection surface as Data Table. Cell boundaries are faint guides for editing and range selection; the active cell and edit boundary carry the strongest emphasis.
Editing and configuration
- Double-click or press Enter to edit. Enter commits; Escape cancels. Drag to select a range, use arrow keys to move, or copy and paste tab-separated cells.
- Set
readOnly,showRowSelection,showRowNumbers,sortable,cellSelection, orresizableindependently. - Each column can define parsing, validation, editable rules, rendering, and a cell-specific completion callback. Validation receives the final proposed rows, the original rows, the TanStack table, and optional external data, so linked rules can be checked before any change is applied.
- Use
tableOptionsfor TanStack Table options,tableColumnfor per-column options, andtableRefto access the live API for the registered features. Grid-level callbacks remain convenient for cell commits, grouped row commits, selections, and sorting.
Implementation
Validation sees the candidate transaction. The ref exposes TanStack's full table instance.
import { useRef } from "react";
import { DataGrid, type DataGridColumn } from "@lenso/ui/data-grid";
import type { DataGridTable } from "@lenso/primitives/data-grid";
type Company = { id: string; name: string };
type Rules = { reservedNames: ReadonlySet<string> };
const tableRef = useRef<DataGridTable<Company>>(null);
const rules: Rules = { reservedNames: new Set(["lenso"]) };
const columns: DataGridColumn<Company, Rules>[] = [
{
id: "name",
header: "Company",
getValue: (row) => row.name,
setValue: (row, value) => ({ ...row, name: String(value) }),
tableColumn: { sortingFn: "alphanumeric" },
validate: (value, row, { rows, data }) => {
const name = String(value).trim();
if (!name) return "Name is required";
if (data?.reservedNames.has(name.toLowerCase())) return "Name is reserved";
return rows.some((other) => other.id !== row.id && other.name === name)
? "Name already exists"
: null;
},
},
];
<DataGrid
label="Companies"
rows={rows}
columns={columns}
getRowId={(row) => row.id}
onRowsChange={setRows}
validationData={rules}
tableOptions={{ enableMultiCellRangeSelection: false }}
tableRef={tableRef}
onCellEditComplete={(change) => saveCell(change)}
onRowEditComplete={(change) => auditRow(change)}
/>;