Skip to content

DataTable

A feature-rich data table built on TanStack Table with sorting, filtering, pagination, and row selection.

  • beta
  • since v0.1.0
  • 18.0 kB
  • data-display
  • table
  • sortable
  • filterable
  • pagination

Column headers use aria-sort; the table carries a <caption> for screen readers; row checkboxes have aria-label.

Preview
Open
tsx

Enable column sorting by passing sortable. Click any column header to toggle ascending / descending order.

Preview
Open
tsx

Pass a filter object with a global string and onGlobalFilterChange handler. Use the toolbar prop to render a search input above the table.

Preview
Open
tsx

Pass pagination with a pageSize to split rows into pages. A Pagination control is rendered below the table automatically.

Preview
Open
tsx
PropTypeDefaultDescription
data*
TData[]
Row data. Each row is rendered once unless paginated; identity tracked by `getRowId`.
columns*
ColumnDef<TData>[]
Column definitions from `@tanstack/react-table`. Each `ColumnDef` provides an `accessorKey`/`accessorFn` that yields the cell value, a `header`, and an optional `cell` renderer. When `selectable` is true an internal `__select` column is prepended automatically.
sortable
boolean
false
Enable click-to-sort on each column that hasn't opted out. Holding shift while clicking adds a secondary sort. Sorted columns expose `aria-sort="ascending|descending|none"` for assistive tech.
selectable
boolean
false
Enable a leading checkbox column for row selection. Header checkbox toggles the entire visible page.
onSelectionChange
((rows: TData[]) => void)
Fires with the live array of selected rows whenever selection changes.
pagination
boolean|DataTablePagination
`true` enables pagination with defaults; pass a {@link DataTablePagination} to customise page size, initial index, or wire an external change listener. When enabled, the pagination footer renders below the table.
filter
DataTableFilter
Controlled global filter — leave undefined to disable filtering.
emptyState
ReactNode
"No results."
Body rendered when `data.length === 0` (after filters applied).
loading
boolean
false
Render skeleton rows instead of data. Useful while waiting on async data.
loadingRows
number
6
Number of skeleton rows shown while `loading` is true.
tableVariant
"line"|"striped"|"grid"|"minimal"
"line"
Visual variant forwarded to the underlying {@link Table}.
tableSize
"sm"|"md"|"lg"
"md"
Size token forwarded to the underlying {@link Table}.
stickyHeader
boolean
Pin the table header to the scroll container's top edge while body scrolls.
toolbar
ReactNode
Optional toolbar rendered above the table (e.g. the search input).
getRowId
((row: TData, index: number) => string)
Custom row identifier — used as the React key and the selection map key.
caption
ReactNode
Caption rendered inside the `<caption>` element for screen readers.
ref
Ref<HTMLDivElement>
  • Sortable column headers carry aria-sort="ascending", aria-sort="descending", or aria-sort="none" to communicate sort state to screen readers.
  • Row selection checkboxes have aria-label="Select row" / aria-label="Select all rows on this page".
  • Provide a caption prop to give the table a meaningful title that is read aloud by screen readers.
  • The empty-state row spans all columns and is announced as a single cell.
  • The loading skeleton rows are visually distinguishable; no ARIA live region is emitted (add one in a wrapper if needed).
  • Use selectable + onSelectionChange to build bulk-action UIs.
  • Use loading + loadingRows to show skeleton rows while data is fetching.
  • Use emptyState with a custom ReactNode for a branded empty experience.
  • Set tableVariant="striped" or tableSize="sm" to pass through to the underlying Table.
  • Use stickyHeader with a fixed-height scrollable wrapper to keep column headers visible.
  • Supply getRowId to use a stable business key (instead of row index) for row selection and re-renders.