<DataTable> props
Every prop, grouped by area. Use the search (top right) to find a setting fast.
Data
| Prop | Type | Default | Description |
|---|---|---|---|
columns | ColumnDef<T>[] | — | TanStack column definitions (+ align, type, wrapText, export options). |
data | T[] | [] | Row data (client mode). |
rowCount | number | — | Total row count (server mode). |
getRowId | (row, index) => string | — | Stable row id; defaults to row[idKey]. |
idKey | keyof T | 'id' | Shorthand row-id field. |
dataMode | 'client' | 'server' | 'client' | Client-held or server-fetched. |
onFetchData | (filters, meta) => Promise<{ data, total }> | — | Server fetch handler. |
initialState | Partial<TableState> | — | Initial sorting/pagination/pinning/visibility/sizing/density. |
stateKey | string | — | Persist view state under this key (see State persistence). |
persist | PersistOptions | — | Tune persistence: storage ('local'/'session'/custom), include, debounceMs. |
onDataStateChange | (state) => void | — | Any table-state change. |
Sorting / Filtering / Pagination
| Prop | Type | Default | Description |
|---|---|---|---|
enableSorting | boolean | true | Column sorting. |
sortingMode | 'client' | 'server' | 'client' | Sort locally or on the server. |
enableGlobalFilter | boolean | true | Toolbar search. |
enableColumnFilter | boolean | false | Column-filter rule builder. |
filterMode | 'client' | 'server' | 'client' | Filter locally or on the server. |
enablePagination | boolean | false | Pagination footer. |
paginationMode | 'client' | 'server' | 'client' | Paginate locally or on the server. |
Selection
| Prop | Type | Default | Description |
|---|---|---|---|
enableRowSelection | boolean | (row) => boolean | false | Selection checkbox column. |
enableMultiRowSelection | boolean | true | Allow multiple selection. |
selectMode | 'page' | 'all' | 'page' | Select-all scope. |
isRowSelectable | ({ row, id }) => boolean | — | Disable specific rows. |
enableBulkActions | boolean | false | Bulk-actions bar. |
renderBulkActions | (selection) => ReactNode | — | Custom bulk actions. |
onSelectionChange | (selection) => void | — | Selection changed. |
Columns
| Prop | Type | Default | Description |
|---|---|---|---|
enableColumnResizing | boolean | false | Drag to resize. |
columnResizeMode | 'onChange' | 'onEnd' | 'onChange' | Live vs on-release. |
enableColumnReordering | boolean | false | Drag headers to reorder. |
enableColumnPinning | boolean | false | Sticky left/right. |
enableColumnVisibility | boolean | true | Show/hide from toolbar. |
Appearance & layout
| Prop | Type | Default | Description |
|---|---|---|---|
density | 'compact' | 'standard' | 'comfortable' | — | Controlled density — overrides the selector. |
defaultDensity | 'compact' | 'standard' | 'comfortable' | 'standard' | Uncontrolled initial density; the selector can still change it. |
striped | boolean | false | Alternate row background. |
hover | boolean | true | Highlight the hovered row. |
fitToScreen | boolean | true | Stretch columns to fill width. |
stickyHeader | boolean | — | Pin the header; on its own it bounds the body at maxHeight (see Height & scrolling). |
stickyFooter | boolean | — | Pin the pagination footer; like stickyHeader, it bounds the body. |
maxHeight | string | number | 480¹ | Cap the scroll viewport; active on its own. ¹Default applied only in a bounded mode. |
height | string | number | — | Fix the grid height ('100%' fills a sized parent); the body scrolls to fill. |
minHeight | string | number | — | Optional floor so a near-empty grid doesn't collapse. |
enableVirtualization | boolean | false | Render only visible rows. |
estimatedRowHeight | number | 52 | Virtualizer row-height estimate. |
getRowClassName | ({ row, index }) => string | — | Conditional row class. |
getCellClassName | ({ row, columnId, value }) => string | — | Conditional cell class. |
Toolbar
| Prop | Type | Default | Description |
|---|---|---|---|
enableDensitySelector | boolean | false | Density menu. |
enableExport | boolean | false | Export menu. |
enableReset | boolean | false | Reset button. |
enableRefresh | boolean | false | Refresh button. |
extraFilter | ReactNode | — | Custom toolbar content (right side by default). |
renderToolbar | (controls) => ReactNode | — | Rearrange the built-in toolbar controls (guide). |
States & customization
| Prop | Type | Default | Description |
|---|---|---|---|
loading | boolean | false | Show skeleton rows. |
noRowsMessage | string | ReactNode | 'No rows' | Empty-state message. |
skeletonRows | number | 5 | Skeleton row count. |
slots | Partial<DataTableSlots> | — | Replace any sub-component. |
slotProps | PartialSlotProps | — | Inject props/sx into parts. |
apiRef | RefObject<DataTableApi<T>> | — | Imperative handle. |
sx | SxProps | — | Root styles. |
onRowClick | (event, row) => void | — | Row click. |
selectOnRowClick | boolean | false | Toggle selection on row click. |
logging | boolean | DataTableLoggingOptions | false | Debug logging. |
Slots & slotProps
slots replaces a part; slotProps injects props/sx into one — the MUI pattern. Slots are a flat
map of descriptive keys (not nested by section); pass only what you want to override, and each falls back
to the built-in.
Structure slots
| Slot | Part |
|---|---|
root, scroller, grid | outer card / scroll area / grid |
header, headerRow, headerCell | header parts |
body, row, cell, detailPanel | body parts |
footer, pagination | footer / pagination |
loadingOverlay, noRowsOverlay | overlays |
Toolbar & control slots
| Slot | Part |
|---|---|
toolbar | the whole toolbar |
searchInput | global search field |
columnFilterControl, columnVisibilityControl, columnPinningControl, densityControl | toolbar menus |
exportButton, refreshButton, resetButton | toolbar buttons |
bulkActionsToolbar | selection bulk-actions bar |
Icon slots
Swap in your own set (e.g. lucide); defaults are built-in line icons. See Custom icons.
| Slot | Used for |
|---|---|
searchIcon, clearIcon | search / clear |
filterIcon, addFilterIcon | column filter |
columnsIcon | columns panel (show/hide, pin, reorder) |
densityIcon, exportIcon, refreshIcon, resetIcon | toolbar buttons |
sortIconAsc, sortIconDesc | header sort |
expandIcon, collapseIcon | row expand / collapse |
slotProps accepts the same keys, plus selectionColumn / expandColumn to configure the
auto-generated checkbox / expander columns — e.g. slotProps={{ selectionColumn: { enablePinning: true } }}.
Height & scrolling
The grid is a flex column — header pinned to the top, footer to the bottom, body scrolling between.
Three height modes: auto (default, grows to content), maxHeight (caps and scrolls), and
height (fixed, or "100%" to fill a sized parent). A bounded height is all the body needs to
scroll — minHeight is not required.
See Height & scrolling for the full guide with a live demo of each mode.
State persistence
Give the grid a stable stateKey and it remembers its view state — pagination, sort, global search,
column filters, column order / width / visibility / pinning, and density — across reloads and remounts,
with no save/restore wiring:
<DataTable columns={columns} data={rows} stateKey="expenses" enablePagination enableColumnPinning />
Try it — sort, paginate, reorder/resize/hide a column, then reload the page: the view comes back.
It reads the saved snapshot into initialState on mount and writes (debounced) on change. Selection and
row expansion are excluded by default. Tune it with persist:
<DataTable
stateKey="expenses"
persist={{
storage: 'session', // 'local' (default) | 'session' | a custom Storage-like object
include: ['sorting', 'pagination', 'columnPinning'], // whitelist (default: all but selection/expansion)
debounceMs: 500, // write throttle (default 300)
}}
/>
SSR-safe (no-ops without window; a custom storage object is honored anywhere). Storage keys are
namespaced as dt:<stateKey>. To forget a saved view (e.g. a "Reset" button), call
clearPersistedState(stateKey, persist?) and remount/reload.
Dark mode & cssVariables themes
The grid derives every colour from your MUI theme, so it follows light/dark automatically — including the
modern setup createTheme({ cssVariables: true, colorSchemes: { light, dark } }): it reads palette values
via theme.vars and emits its mode-dependent defaults with applyStyles('dark'). To customise grid
colours per scheme, use createDataTableTheme (palette + optional darkPalette), which
emits colorSchemes overrides that compose cleanly with a cssVariables app theme.