Skip to main content

DataGrid

A flexible, Vercel-style data grid component for displaying tabular data with sorting, selection, pagination, and keyboard navigation. Designed for dashboards and admin interfaces with strong accessibility support.


Usage

Basic usage

import { DataGrid } from '@nofinite/nui';

<DataGrid columns={columns} rows={rows} />;

With common interaction

<DataGrid
columns={columns}
rows={rows}
selectable
pageSize={5}
onRowClick={(row) => console.log(row)}
/>

Variants

DataGrid does not have visual variants. Customization is achieved via:

  • Column alignment
  • Custom cell renderers
  • Row actions slot
  • CSS overrides via className
<DataGrid columns={columns} rows={rows} />

Guidelines:

  • Use column align for numeric or status-like data.
  • Use render for complex cell content.
  • Use renderRowActions for per-row controls.

Sizes

The grid adapts to its container and does not expose explicit size props.

Control sizing via:

  • pageSize (number of rows per page)
  • Container width / height
  • Column width
<DataGrid
columns={[
{ key: 'name', title: 'Name', width: 200 },
{ key: 'email', title: 'Email' },
]}
rows={rows}
pageSize={10}
/>

States

Empty state

Automatically shown when rows is empty.

<DataGrid columns={columns} rows={[]} />

Selected state

Enabled via selectable. Selected rows are visually highlighted.

<DataGrid selectable columns={columns} rows={rows} />

Focused state

  • Managed internally via keyboard navigation.
  • Visible focus outline when navigating with keys.

Native Props / Composition

DataGrid renders a semantic grid structure using <div> elements with ARIA roles.

Extra props can be passed via composition hooks:

<DataGrid className="my-custom-datagrid" columns={columns} rows={rows} />

Props

PropTypeDefaultDescription
columnsDataGridColumn[]Column definitions (key, title, sorting, render, alignment)
rowsDataRow[]Data rows to render
pagenumberControlled current page
pageSizenumber10Rows per page
onPageChange(page: number) => voidPage change callback
selectablebooleanfalseEnables row selection via checkboxes
selectedRowIdsSet<string | number>Controlled selected rows
onSelectionChange(ids: Set<string | number>) => voidSelection change callback
onRowClick(row: DataRow) => voidFired when a row is clicked
renderRowActions(row: DataRow) => ReactNodeSlot for row-level actions
disablePaginationbooleanfalseDisables pagination entirely
classNamestring""Additional CSS class names

Behavior Notes

  • Sorting cycles through: ascending → descending → none.
  • Sorting is client-side and stable.
  • Pagination is client-side.
  • Selection can be controlled or uncontrolled.
  • If row.id is missing, an internal fallback ID is generated.
  • Clicking a row can both select it and trigger onRowClick.

Example:

<DataGrid selectable onRowClick={(row) => console.log('Clicked:', row)} />

Accessibility

  • Uses role="grid", row, gridcell, and columnheader.

  • Sorting state exposed via aria-sort.

  • Row selection exposed via aria-selected.

  • Keyboard support:

    • ArrowUp / ArrowDown – move focus
    • Home / End – jump to first / last row
    • PageUp / PageDown – change page
    • Enter – select row / trigger click
  • Checkboxes include descriptive aria-labels.


Layout

  • Header is sticky by default.
  • Body scrolls vertically when content exceeds max height.
  • Grid expands horizontally to fit columns.
  • Fully responsive with adaptive cell padding.
<div style={{ maxWidth: 900 }}>
<DataGrid columns={columns} rows={rows} />
</div>

Best Practices

Do

  • Provide stable id values for rows.
  • Use render for formatted or interactive cells.
  • Use renderRowActions for contextual row actions.
  • Enable selectable only when bulk actions are needed.

Don’t

  • Use DataGrid for very small datasets where a simple list works.
  • Perform heavy server-side logic inside cell renderers.
  • Nest complex focusable components without considering keyboard flow.
  • Rely on auto-generated row IDs for persistent selection.