<DataTable> props
Every prop, grouped by area. Use the search (top right) to find a setting fast.
How to read these tables — the Type column doubles as the list of possible values (e.g. a union
like 'client' | 'server' is the allowed set); Default is what you get when you omit the prop; the
Description says what it does and when to reach for it. Naming follows a few conventions:
| Pattern | Meaning | Example |
|---|---|---|
enableX | Feature toggle (boolean) | enableSorting, enablePagination |
xMode | Client-side vs server-side | filterMode, paginationMode |
onXChange | State-change callback — see Events | onSortingChange |
renderX | Custom render function | renderDetailPanel, renderBulkActions |
| adjective | Visual modifier | striped, hover, fitToScreen |
T is your row type — pass it as <DataTable<User> …> for typed columns, callbacks, and apiRef. Only
the most-used props are listed here; deprecated v1 aliases and niche export/logging options live in the
TypeScript types. Feature deep-dives are
linked from each section.
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
See Sorting · Filtering · Quick Filter · Pagination.
| Prop | Type | Default | Description |
|---|---|---|---|
enableSorting | boolean | true | Click headers to sort. Turn off for a fixed-order grid. |
sortingMode | 'client' | 'server' | 'client' | 'client' sorts in memory; 'server' hands the sort model to onFetchData — use for datasets you don't hold locally. |
onSortingChange | (sorting) => void | — | Observe the sort model (sync a URL, analytics). |
enableGlobalFilter | boolean | true | Collapsible toolbar quick-search across all columns. |
enableColumnFilter | boolean | false | Per-column rule builder (field · operator · value) with an active-count badge. |
filterMode | 'client' | 'server' | 'client' | Where matching happens (shared by global + column filters). 'server' → filter via onFetchData. |
enablePagination | boolean | false | Show the footer pager. Off = render every row (pair with virtualization for big data). |
paginationMode | 'client' | 'server' | 'client' | 'server' requests one page at a time via onFetchData — needs rowCount. |
rowsPerPageOptions | number[] | [5,10,25,50,100] | Page-size choices; [] hides the selector. |
Selection
See Selection.
| Prop | Type | Default | Description |
|---|---|---|---|
enableRowSelection | boolean | (row) => boolean | false | Add the checkbox column. Pass a predicate to allow selection only on some rows. |
enableMultiRowSelection | boolean | true | false = single-select (radio-like) — use for "pick one". |
selectMode | 'page' | 'all' | 'page' | Whether "select all" spans the current page or the whole (filtered) dataset. |
isRowSelectable | ({ row, id }) => boolean | — | Disable specific rows' checkboxes (e.g. locked records). |
enableBulkActions | boolean | false | Show the contextual bar (count + Clear) when rows are selected. |
renderBulkActions | (selection) => ReactNode | — | Your actions for the bulk bar (Delete, Assign…). selection carries include/exclude ids. |
enableClipboardCopy | boolean | false | Add a Copy action to the bulk bar (TSV to clipboard). |
onSelectionChange | (selection) => void | — | React to selection (enable a button, show a banner). |
Columns
See Columns · Column pinning · Cells.
| Prop | Type | Default | Description |
|---|---|---|---|
enableColumnResizing | boolean | false | Drag a header edge to resize; persists with stateKey. |
columnResizeMode | 'onChange' | 'onEnd' | 'onChange' | 'onChange' resizes live as you drag; 'onEnd' waits for release (steadier for very wide grids). |
enableColumnReordering | boolean | false | Drag headers to reorder (also exposed in the columns panel). |
enableColumnPinning | boolean | false | Freeze columns left/right; seed with initialState.columnPinning. |
enableColumnVisibility | boolean | true | Show/hide checkboxes in the toolbar columns panel. |
enableColumnMenu | boolean | true | Per-column header ⋮ menu (sort, hide, autosize). Opt one column out with columnDef.disableColumnMenu. |
onColumnOrderChange / onColumnPinningChange / onColumnVisibilityChange / onColumnSizingChange | (state) => void | — | Observe each column-layout change — see Events. |
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 |
|---|---|---|---|
toolbarVariant | 'icon' | 'text' | 'icon' | Icon-only (tooltip) or icon + label buttons (guide). |
enableDensitySelector | boolean | false | Density menu. |
enableExport | boolean | false | Export menu. |
enableReset | boolean | false | "Reset layout" button — restores the column layout only (no data reload). |
resetActions | ResetLayoutAction[] | ['columnOrder','columnPinning','columnSizing'] | What Reset restores. Add 'columnVisibility', 'rowPinning', 'filters', 'sorting', 'pagination'. |
enableRefresh | boolean | false | "Refresh data" button — re-fetches data (onFetchData in server mode). |
enableListView | boolean | false | Grid ⇄ list view toggle. |
listView / onListViewChange | boolean / (next) => void | — | Controlled list-view mode. |
renderListItem | (params) => ReactNode | — | Render a row as a full-width list item. |
rowHeight | number | — | Fixed row height in px (overrides density). |
extraFilter | ReactNode | — | Custom toolbar content (right side by default). |
footerFilter | ReactNode | — | Custom content on the left of the footer, opposite pagination (e.g. a "show deleted" toggle). The footer appears whenever this or enablePagination is set. |
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 | — | Fires when a row is clicked (not when a checkbox / expander / action inside it is). |
selectOnRowClick | boolean | false | Clicking anywhere in a row toggles its selection (needs enableRowSelection; respects single/multi mode + per-row selectability). Composes with onRowClick. |
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, densityControl | toolbar menus |
viewsControl | saved-views control |
exportButton, refreshButton, resetButton | toolbar buttons |
bulkActionsToolbar | selection bulk-actions bar |
Each control is both swappable (slots.<key>) and injectable (slotProps.<key>) — pass a
component to replace it, or props/sx to style the built-in one.
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 / actionsColumn to
configure the auto-generated checkbox / expander / row-actions columns — e.g.
slotProps={{ selectionColumn: { enablePinning: true } }}.
Every slotProps entry's sx, className, and style merge with the built-in styling (yours wins
per-property) — a structural part never loses its required roles, refs, or keyboard wiring, and the root's
design tokens are never clobbered. Leaf controls (pagination, toolbar buttons) spread your props last,
so a deliberate override wins.
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.