DataTable
Feature-rich data grid with client-side sorting, pagination, and row selection. Built on top of the Table primitive — use Table directly when you only need static markup.
Anatomy
<DataTable
columns={columns} {/* ColumnDef[] */}
data={rows} {/* TData[] */}
getRowId={…} {/* stable row key */}
selectable {/* checkbox column */}
pageSize={10} {/* enables pagination footer */}
/>Examples
| Name | Role | Status | Joined | |
|---|---|---|---|---|
| Alice Chen | alice@example.com | Admin | Active | 2023-01-15 |
| Bob Martin | bob@example.com | Editor | Active | 2023-03-22 |
| Carol Davies | carol@example.com | Viewer | Inactive | 2023-05-10 |
| Dan Hughes | dan@example.com | Editor | Active | 2023-07-04 |
| Eva Torres | eva@example.com | Admin | Active | 2023-09-18 |
| Frank Müller | frank@example.com | Viewer | Pending | 2024-01-03 |
| Grace Kim | grace@example.com | Editor | Active | 2024-02-14 |
| Henry Walsh | henry@example.com | Viewer | Inactive | 2024-03-30 |
| Isla Grant | isla@example.com | Editor | Active | 2024-05-01 |
| James Park | james@example.com | Viewer | Pending | 2024-06-12 |
| Karen Bell | karen@example.com | Admin | Active | 2024-07-07 |
| Leo Santos | leo@example.com | Editor | Active | 2024-08-20 |
Pagination
| Name | Role | Status | Joined | |
|---|---|---|---|---|
| Alice Chen | alice@example.com | Admin | Active | 2023-01-15 |
| Bob Martin | bob@example.com | Editor | Active | 2023-03-22 |
| Carol Davies | carol@example.com | Viewer | Inactive | 2023-05-10 |
| Dan Hughes | dan@example.com | Editor | Active | 2023-07-04 |
| Eva Torres | eva@example.com | Admin | Active | 2023-09-18 |
12 resultsRows per page
Row selection
| Name | Role | Status | Joined | ||
|---|---|---|---|---|---|
| Alice Chen | alice@example.com | Admin | Active | 2023-01-15 | |
| Bob Martin | bob@example.com | Editor | Active | 2023-03-22 | |
| Carol Davies | carol@example.com | Viewer | Inactive | 2023-05-10 | |
| Dan Hughes | dan@example.com | Editor | Active | 2023-07-04 | |
| Eva Torres | eva@example.com | Admin | Active | 2023-09-18 |
12 resultsRows per page
Empty state
| Name | Role | Status | Joined | |
|---|---|---|---|---|
No users found Try adjusting your search or filter. | ||||
Props
columns*
ColumnDef<TData>[]
Column definitions — key, header, optional cell renderer, sort, align.
data*
TData[]
Array of row data objects.
getRowId
(row: TData, index: number) => string
Returns a stable unique id per row. Defaults to row index.
selectable= false
boolean
Adds a checkbox column for row selection.
selectedRows
string[]
Controlled selected row ids.
onSelectionChange
(ids: string[]) => void
Called when the selection changes.
pageSize
number
Enables client-side pagination with this as the initial page size.
pageSizeOptions= [10, 20, 50, 100]
number[]
Available page size options in the footer selector.
striped= false
boolean
Alternating row background.
onRowClick
(row: TData) => void
Makes rows clickable — adds hover state and cursor pointer.
emptyTitle= 'No results'
string
Heading shown when data is empty.
emptyDescription
string
Supporting text shown when data is empty.
emptyIcon
ReactNode
Icon shown in the empty state. Defaults to a table icon.
className
string
Additional classes on the wrapper.
| Prop | Type | Default | Description |
|---|---|---|---|
| columns* | ColumnDef<TData>[] | — | Column definitions — key, header, optional cell renderer, sort, align. |
| data* | TData[] | — | Array of row data objects. |
| getRowId | (row: TData, index: number) => string | — | Returns a stable unique id per row. Defaults to row index. |
| selectable | boolean | false | Adds a checkbox column for row selection. |
| selectedRows | string[] | — | Controlled selected row ids. |
| onSelectionChange | (ids: string[]) => void | — | Called when the selection changes. |
| pageSize | number | — | Enables client-side pagination with this as the initial page size. |
| pageSizeOptions | number[] | [10, 20, 50, 100] | Available page size options in the footer selector. |
| striped | boolean | false | Alternating row background. |
| onRowClick | (row: TData) => void | — | Makes rows clickable — adds hover state and cursor pointer. |
| emptyTitle | string | 'No results' | Heading shown when data is empty. |
| emptyDescription | string | — | Supporting text shown when data is empty. |
| emptyIcon | ReactNode | — | Icon shown in the empty state. Defaults to a table icon. |
| className | string | — | Additional classes on the wrapper. |
ColumnDef
key*
string
Matches a property on the data object. Used for default sorting and cell rendering.
header*
string
Column heading label.
sortable
boolean
Enables click-to-sort on this column.
align= 'left'
'left' | 'center' | 'right'
Text alignment for header and cells.
cell
(row: TData, index: number) => ReactNode
Custom cell renderer. Falls back to String(row[key]).
width
string
Fixed column width, e.g. '120px'.
| Prop | Type | Default | Description |
|---|---|---|---|
| key* | string | — | Matches a property on the data object. Used for default sorting and cell rendering. |
| header* | string | — | Column heading label. |
| sortable | boolean | — | Enables click-to-sort on this column. |
| align | 'left' | 'center' | 'right' | 'left' | Text alignment for header and cells. |
| cell | (row: TData, index: number) => ReactNode | — | Custom cell renderer. Falls back to String(row[key]). |
| width | string | — | Fixed column width, e.g. '120px'. |