Data Grid

A spreadsheet for your application. Edit cells, select ranges, filter records, and work through thousands of rows with a frozen first column and live summaries.

Renewals

Total Results10,000 rows

Use arrow keys to navigate, Shift and arrows to select cells, and Enter or F2 to edit. Copy and paste cells with your keyboard. Column headings sort; column separators resize with arrow keys.

Northwind Freight
Owen Park
Latin America
Closed won
40
$9,600
49%
Lumen Freight
Tyler Hayes
Europe
Closed won
105
$37,800
90%
Cedar Freight
Tyler Hayes
Latin America
Proposal
230
$96,600
64%
Brightline Freight
Marcus Johnson
Asia Pacific
Proposal
115
$41,400
78%
Harbor Freight
Daniel Kim
Latin America
Committed
10
$4,200
72%
Pinecrest Freight
Marcus Johnson
Europe
Closed won
470
$169,200
72%
Atlas Freight
Sarah Bennett
Latin America
Discovery
45
$16,200
95%
Summit Freight
Owen Park
Asia Pacific
Negotiation
255
$107,100
93%
Fieldstone Freight
Marcus Johnson
Europe
Discovery
660
$237,600
82%
Evergreen Freight
Marcus Johnson
Latin America
Negotiation
46
$13,800
56%
Meridian Freight
Owen Park
Asia Pacific
Discovery
119
$42,840
73%
Redwood Freight
Daniel Kim
Europe
Committed
192
$80,640
90%
Westbridge Freight
Tyler Hayes
North America
Proposal
265
$63,600
41%
Sum3.3M
Sum$1.1B
Avg67.5%
A1Count 1

Installation

Add the free Data Grid with our CLI. It includes the BoardUI controls and private data helpers it uses:

Dark mode ready - this component follows BoardUI semantic tokens automatically. Set up theme switching.

The CLI copies the component source (with its internal dependencies) into your project and installs any required npm packages.

npx boardui@latest add data-grid

Using a shared UI package or custom import aliases? Configure your installation paths before running the CLI. Copy-paste examples use the default imports.

Columns and editing

Pass typed columns, your data, and a unique, stable getRowId. Provide onDataChange to enable editing. Text, number, and select editors reuse BoardUI inputs and selects. Set bounds with min and max, or reject values with validate.

Use format for cell display and formatSummary for sum, average, or count footers. Set editable= on individual columns. Formatting changes presentation; editing, copying, and exporting use the underlying values.

const columns: DataGridColumn<Account>[] = [ { key: "account", header: "Account", width: 220, validate: (value) => String(value).trim() ? undefined : "Account cannot be empty." }, { key: "stage", header: "Stage", type: "select", options: ["Discovery", "Proposal", "Closed won"] }, { key: "seats", header: "Seats", type: "number", min: 0, summary: "sum" }, { key: "arr", header: "ARR", type: "number", min: 0, editable: false, summary: "sum", formatSummary: (value) => `$${value.toLocaleString("en-US")}` },]; // Omit onDataChange to make every cell read-only.<DataGrid aria-label="Accounts" data={data} columns={columns} getRowId={getRowId} />

Search, filter, and export

Search across all columns, click a heading to cycle through ascending, descending, and original order, or filter by exact values. Select columns automatically appear in the Filter menu; add filterable to other columns. Hide columns, resize their dividers, and switch between comfortable and compact rows.

The first visible column stays frozen beside the row numbers. On narrow screens it scrolls with the other columns so every cell remains reachable. Row checkboxes select records independently of cell ranges; the header checkbox toggles all filtered rows. Selecting rows shows the count and Delete, Copy, and Export actions in the toolbar. Copy uses tab-separated values; export downloads a CSV, both using visible columns and selected visible records. Delete requires onDataChange and can be undone. Clear the selection to return to the search and view controls. Summaries always reflect the filtered records.

Keyboard and clipboard

Tab into the grid and use arrow keys to move between cells. Hold Shift to extend a range, or drag across cells with the mouse. Home and End move across a row; add ⌘ or Ctrl to jump to the first or last record. Page Up and Page Down move by a viewport. ⌘/Ctrl+A selects all cells.

Select a cell with options to reveal its dropdown, then click the chevron to choose a value. Double-click, Enter, or F2 opens the cell editor. Enter saves and moves down; Shift+Enter moves up. Tab saves and moves to the next cell. Escape cancels. Copy a range and paste tab-separated spreadsheet data with the usual keyboard shortcuts. Invalid values reject the entire paste. Undo and redo apply to cell edits, pastes, and row deletions, with up to 100 transactions kept for the mounted grid.

Give each grid an aria-label. Wrap right-to-left regions in DirectionProvider; frozen columns, menus, and horizontal arrow keys follow the reading direction.

10,000 rows, a small viewport

The preview above contains 10,000 actual records. Fixed-height virtualization mounts only the rows in and around the viewport. The header and summary remain outside the scrolling body; a progressive blur softens the top edge as you scroll. Set height to change the viewport height.

Search, sorting, filtering, and summaries run in the browser over the provided data. Cell selection and edits follow stable row IDs as records move. Persist changes in your onDataChange handler. Remount the grid with a new React key when switching to a different dataset to reset view state and edit history.

Right-to-left and read-only

Use DirectionProvider to set the reading direction. This read-only example freezes the first column on the right and mirrors horizontal keyboard navigation. Your column labels and record values can use any language.

Total Results2 rows

Use arrow keys to navigate, Shift and arrows to select cells, and Enter or F2 to edit. Copy and paste cells with your keyboard. Column headings sort; column separators resize with arrow keys.

نورث ويند
أوروبا
40
لومن
آسيا
105
Sum145
A1Count 1Read-only