Data Grid

A spreadsheet-like grid: move between cells with the arrow keys and edit values in place, with validation.
Stable
Web
iOS
Android
@advui/data
Source

Editable, with validation

Township
Sector
Target
Reached
Progress
Hakha
Health
5,000
4,200
84%
Sittwe
WASH
12,000
9,800
82%
Labutta
Food Security
8,000
8,150
102%
Myitkyina
Protection
3,500
Mawlamyine
Education
2,600
1,900
73%
Double-click a cell, or press Enter, to edit.

Installation

pnpm
pnpm add @advui/data
npm
npm install @advui/data

Usage

import { DataGrid, type DataGridColumn } from '@advui/data'

const columns: DataGridColumn<Row>[] = [
  { id: 'township', header: 'Township' },
  { id: 'reached', header: 'Reached', type: 'number', editable: true },
]

<DataGrid aria-label="Reach by township" data={rows} onDataChange={setRows} columns={columns} />

Examples

Read-only, with custom cells

Organization
Type
Townships
Status
Shwe Health
NNGO
14
Active
Green Valley
NNGO
9
Active
River Delta Relief
INGO
21
Paused
Care Myanmar
INGO
33
Active

API reference

DataGrid

PropTypeDefaultDescription
aria-label requiredstring—Names the grid.
columns requiredDataGridColumn<T>[]—Column definitions (below).
dataT[]—The rows. Accepted edits come back as a new array.
defaultDataT[]—Starting `data` when uncontrolled.
onDataChange(data: T[]) => void—Called with the new `data`.
onCellChange(change: DataGridCellChange<T>) => void—One accepted edit: `row`, `rowId`, `rowIndex`, `columnId`, `value`, `previousValue`. Save it here.
getRowId(row, index) => string`row.id`, then the indexStable id for React keys and `onCellChange`.
getRowLabel(row) => stringthe first columnNames the row in cell names and errors ("Reached, Hakha").
readOnlybooleanfalseNo editing.
size'sm' | 'md''md'Row height.
labelsPartial<DataGridLabels>—Edit hint and error text, for translation.

DataGridColumn<T>

PropTypeDefaultDescription
id requiredstring—Key; the row field by default.
header requiredstring—Header text.
editablebooleanfalseCells can be edited.
type'text' | 'number''text'`number` right-aligns, shows the number keyboard and parses the input.
validate(value, row) => string | null—Return a message to reject an edit. The cell stays open with the error.
accessor(row: T) => string | number | null | undefined—Reads a value that is not a plain field. Default: `row[id]`.
setValue(row: T, value: string | number | null) => T—Writes an edited value that is not a plain field; returns the new row.
format(value, row) => string—Display text, e.g. thousands separators.
cell(row) => ReactNode—Custom display content.
widthnumber160Pixels. The grid scrolls sideways when wider than its container.
align'start' | 'center' | 'end'—Alignment.

Accessibility

  • Web follows the WAI-ARIA grid pattern: a named grid with row, columnheader and gridcell roles, row and column indexes, and one tab stop (the active cell).
  • The editor is a text field named by its column and row ("Reached, Hakha").
  • A rejected edit keeps the field open, marks it aria-invalid, and says why in a polite live region under the grid.
  • On iOS and Android each cell reads its column, row and value; editable cells are buttons with a "Double-tap to edit" hint.
Keyboard interactions
KeyAction
Arrow keysMove between cells.
Home / EndFirst or last cell in the row (with Ctrl or ⌘: in the grid).
Page Up / Page DownMove five rows.
Enter / F2Edit the cell. Typing a character starts editing with it.
Delete / BackspaceEdit the cell, starting empty.
Enter / Tab (editing)Save and move down or right (Shift: up or left).
Escape (editing)Cancel the edit.
TabLeave the grid.

Responsive behavior

Columns have fixed widths; the grid scrolls sideways on narrow screens.

Platform notes

Web
Double-click a cell to edit it. Clicking elsewhere saves the edit, or drops it when it is invalid.
iOS
Tap an editable cell to edit; the keyboard’s Done key saves.
Android
Same as iOS.
Since v0.6.0Last updated Nov 2, 2026Edit this page on GitHub