Tangible Design System · @tangible/ui 0.2.29 · Interactive version · Markdown

DataTable

import { DataTable } from '@tangible/ui';

Interactive docs and examples: DataTable in Storybook.

DataTable props

Prop Type Default Description
columns ColumnDef<T, unknown>[] TanStack column definitions. The selection column is injected, not declared.
data T[] Row data. Memoize it, or pass autoResetPageIndex={false} — see below.
aria-label? string Defines a string value that labels the current element.
aria-labelledby? string Identifies the element (or elements) that labels the current element.
autoResetPageIndex? boolean TanStack's automatic page-0 reset when sorting or data identity change. Defaults to true when pageIndex is uncontrolled, false when controlled — a controlled parent owns the index, and the auto-reset would race it back to 0 on every re-render that recreates data (parent re-renders on page change → new array identity → reset). Uncontrolled consumers who setState inside onPageIndexChange while passing a derived (unmemoized) data array hit the same loop: pass false here or memoize data.
className? string
defaultSorting? SortingState [] Initial sort state. Sorting stays internal — this only seeds it.
emptyMessage? React.ReactNode 'No results' Shown in place of rows when data is empty.
enableRowSelection? boolean false
getRowId? (row: T, index: number) => string | number
getRowLabelForSelection? (row: T, index: number) => string
getRowProps? ( row: TanRow<T> ) => Omit<React.ComponentProps<'tr'>, 'key' | 'children' | 'dangerouslySetInnerHTML'> Extra props for each body <tr> — the escape hatch for row-level interaction: keyboard cursors, row click shortcuts, data-* hooks, context menus. Consumer className is merged after the built-in row classes; data-selected and the is-selected class always reflect actual selection state and cannot be overridden. role/aria-* are NOT guarded — overriding role on a <tr> removes it from the table's accessibility tree, so only do that as part of a deliberate pattern (e.g. rows in a role="grid" table keep role="row"). Loading/empty placeholder rows are not affected.
initialPageSize? number
labels? DataTableLabels Override hardcoded English strings for i18n. Unset keys use English defaults.
loading? boolean false Replaces the body with a loading row while true.
loadingMessage? React.ReactNode 'Loading...' Shown in place of rows while loading.
onPageIndexChange? (pageIndex: number) => void Fires with the requested 0-based page index whenever anything asks for a page change — pager clicks, page-size changes (TanStack re-anchors to keep the top row visible), the auto page-0 reset (see autoResetPageIndex), or an out-of-range controlled pageIndex being clamped into range. Fires in both controlled and uncontrolled modes. Note: 0-based, unlike Pager's 1-based onPageChange (the built-in pager converts).
onRowSelectionChange? (updater: Updater<RowSelectionState>) => void
onSelectionChange? (selectedRows: T[], selectedIds: (string | number)[]) => void
pageIndex? number Controlled page index (0-based, matching TanStack). When set, the parent owns paging: the built-in pager requests changes via onPageIndexChange, but the page only moves when this prop updates. Page size stays internal either way. Controlled/uncontrolled is locked at mount.
pageSizeOptions? number[] [10, 20, 50]
paginationMaxNumbers? number 7
paginationMode? "ends" | "full" | "simple" | "smart" 'smart'
paginationNavStyle? "icon" | "text" 'text'
renderBulkBar? (args: BulkSelectionRenderArgs<T>) => React.ReactNode
renderPagination? (table: TanTable<T>) => React.ReactNode
rowSelection? RowSelectionState

Also accepts the standard attributes of TableHTMLAttributes (data-*, aria-*, event handlers), passed to the element it renders.

Examples

Other stories: Basic, Empty, With Actions, With Bulk Select (interactive page).

Component API tokens

Read via fallback, never declared. Set one on an ancestor to restyle every instance under it.