Skip to content
Data Display

DataTable

A table built on TanStack Table: sorting, filtering, pagination, row selection, and column visibility.

Full Example

Alex Chenalex@example.comEngineering
Active
Sarah Kimsarah@example.comDesign
Active
James Wilsonjames@example.comProduct
Pending
Maria Garciamaria@example.comEngineering
Active
David Parkdavid@example.comMarketing
Inactive
0 of 5 row(s) selected.
Page 1 of 1

Direction

Column order follows the columns prop, which means in RTL the first column still renders at the start (now visually on the right) and the last column at the end. If your data is semantically ordered — e.g., timestamp then description — you may want to reverse column definitions for RTL users so the reading flow stays natural. Sort indicators and header chevrons flip automatically via logical CSS properties.

API Reference

DataTable

PropTypeDefaultDescription
columns
required
ColumnDef<TData, TValue>[]TanStack Table column definitions that configure headers, cells, sorting, and filtering.
data
required
TData[]Array of row objects to render in the table.
toolbarReact.ReactNodeOptional toolbar element rendered above the table, typically containing search inputs and view options.
classNamestringAdditional CSS classes applied to the outer wrapper.

DataTableColumnHeader

PropTypeDefaultDescription
column
required
Column<TData, TValue>TanStack Table column instance used to read and toggle sort state.
title
required
stringDisplay text for the column header.

createSelectColumn

PropTypeDefaultDescription
ReturnColumnDef<TData>Returns a checkbox selection column definition. Add it as the first entry in your columns array to enable row selection.

Import

import {
  DataTable,
  DataTableColumnHeader,
  createSelectColumn,
} from "@mikenotthepope/substrateui"

Labels

The largest label set in the set, because a data table is mostly furniture — sort state, selection counts, and pagination are all announced text. Override one instance with the labels prop on the component, or every instance at once through LabelsProvider's dataTable key — the provider is how you translate the set once instead of at each call site.

PropTypeDefaultDescription
previous / nextstring"Previous" / "Next"The pagination buttons.
noResultsstring"No results."Empty-state row.
viewstring"View"The column-visibility trigger.
toggleColumnsstring"Toggle columns"Accessible name for that trigger.
selectAll / selectRowstring"Select all" / "Select row"The header and row checkboxes, which have no visible label.
rowsSelected(selected, total) => string"n of m row(s) selected."Selection summary. A function because the plural rule is the caller's language's, not English's.
pageOf(page, total) => string"Page n of m"Page indicator.
sortedAscending(title) => string"…, sorted ascending. Click to sort descending."Announced sort state, and what a click will do next.
sortedDescending(title) => string"…, sorted descending. Click to remove sort."As above, one step round the cycle.
notSorted(title) => string"…, not sorted. Click to sort ascending."The unsorted case.

Accessibility

Always provide an accessible label for the table, either via the toolbar prop (which typically contains context identifying what the table holds) or by wrapping the DataTable in a landmark with aria-label.

Sortable columns use DataTableColumnHeader, which renders as a button with aria-sort reflecting the current sort state, so screen reader users know which column is sorted and in which direction.

Row selection (via createSelectColumn) uses Checkbox, which is keyboard-accessible and screen-reader-friendly out of the box.