Changelog
All notable changes to @ackplus/mui-tanstack-data-grid. This project follows
Semantic Versioning and the Keep a Changelog
format: each release groups changes as Added (new features), Changed (behaviour/build), Fixed
(bug fixes), and Docs.
Upgrading is safe within a major version —
1.xreleases are backward compatible. Install a specific version withnpm install @ackplus/mui-tanstack-data-grid@<version>.
1.21.2 — 2026-07-25
Backward compatible.
Fixed
- Nested
accessorKeycolumns no longer misalign. Columns that share a dotted path prefix (e.g.unit.user.firstNameandunit.user.lastName) used those ids in CSS width variables (--col-<id>-size). CSSvar()treats.as ending the property name, so sibling nested columns collapsed onto the same broken width and headers/cells drifted. Width vars now sanitize dots to underscores for CSS only —column.id/ filter / sort / server payloads still use the dotted path. No customidremapping needed.
1.21.1 — 2026-07-12
Backward compatible.
Fixed
- Labelled toolbar (
toolbarVariant="text") polish. The icon + label controls now use a medium font weight (was inheriting the app theme's often-bold button weight), even padding across every control (dropped MUI's 64pxmin-width, so a short label like "Views" pads the same as "Refresh data"), and a consistently-sized, slightly-muted icon aligned with the label.
1.21.0 — 2026-07-12
Backward compatible.
Added
- Rebuilt the per-column ⋮ menu into a full MUI-X/AG-Grid-style menu, with items that appear
dynamically by state:
- Sort — the active direction is hidden and Clear sort appears; disabled on non-sortable columns.
- Pin (
enableColumnPinning) — Pin to left / Pin to right; a pinned column shows Unpin column + the opposite side. - Filter (
enableColumnFilter) — Filter opens the toolbar filter panel with this column pre-selected; a filtered column shows a red dot on its ⋮ and a Clear filter item that clears only that column's filter. - Hide column + Manage columns (opens the toolbar Columns panel).
- Structure: sort · pin · filter · ─── · hide · manage. Full keyboard nav, disabled states, and the menu closes after each action.
- New imperative API:
api.filtering.openColumnFilter(columnId),api.filtering.clearColumnFilter(columnId), andapi.columnVisibility.openPanel()— the shared engine channels the menu uses (no duplicate state).
Changed
- Compact toolbar/menu badges. The filter count badge and the saved-views / filter-active dots are smaller, so they no longer overlap the icon glyph.
Fixed
- The ⋮ Filter and Manage columns items are gated to the built-in toolbar controls, so they're
never dead actions — a reorder-only grid now mounts the toolbar, and a custom
slots.columnFilterControl/slots.columnVisibilityControlhides the item it can't drive (Clear filter still works, since it goes straight through the API). Also hardenedclearColumnFilteragainst a partial persisted filter state.
Removed
- Autosize is no longer in the ⋮ menu (still available by double-clicking the column resize handle).
1.20.5 — 2026-07-12
Backward compatible.
Fixed
- The selection ("bulk actions") bar is now themeable. Its background was a hardcoded
primary.mainwith no override path — no--dt-*token, no styled slot, and the default component droppedslotProps.bulkActionsToolbar. The bar is now a first-classbulkActionsToolbarstyled slot whose surface reads two new tokens,--dt-bulkbar-bg/--dt-bulkbar-fg(defaulting frompalette.primary.main/palette.primary.contrastText, scheme-aware). Retint it any of three ways — the tokens (sx={{ '--dt-bulkbar-bg': … }}), themestyleOverrides.bulkActionsToolbar, orslotProps.bulkActionsToolbar(itssx/className/ rest now reach the bar). The bar overlays the toolbar, so keep the background opaque.
1.20.4 — 2026-07-11
Backward compatible.
Fixed
selectOnRowClicknow works. The prop was declared in the public types but never wired up — a dead prop (setting it did nothing). It now toggles a row's selection when you click anywhere in the row (needsenableRowSelection; respects single/multi mode and per-rowisRowSelectable). Clicks on the checkbox, row expander, action buttons, or an editing cell don't trigger it (they stop propagation), and it composes withonRowClick— both run when both are set.
1.20.3 — 2026-07-11
Backward compatible.
Fixed
- Clicking a row's selection checkbox or expand toggle no longer also fires
onRowClick. The auto-generated selection column (the row checkbox and the select-all header checkbox) and the row-expansion button didn't stop click propagation — so on a grid with both row selection/expansion and anonRowClick(e.g. one that navigates to a detail page), ticking the box or expanding a row also triggered the row click. They nowstopPropagation(matching the actions cell): the checkbox still toggles selection, the button still expands, and clicking a normal cell still firesonRowClick.
1.20.2 — 2026-07-11
Backward compatible.
Fixed
- Column resize no longer jumps on the first drag. Under
fitToScreen, an untouched column is flex-grown wider than its basesize; the instant a resize wrotecolumnSizing, the grow switched off and the width snapped back to that base — a visible leftward jump before the drag caught up. The resize now seeds the column's current rendered width at mouse-down (so it starts from what you see), turning the flex→fixed switch into a no-op — resizing is smooth from the first pixel and neighbouring columns keep their width. The native drag math,onChange/onEndmodes, touch, and RTL are unchanged.
1.20.1 — 2026-07-11
Backward compatible.
Fixed
footerFilternow renders. The prop was declared onDataTableProps(and documented) but the render layer never read it — a dead prop since it was introduced. It now renders on the left of the footer, opposite pagination (mirroring howextraFiltersits on the right of the toolbar), so a "show deleted" soft-delete toggle or any custom footer control appears as intended. The footer now shows wheneverfooterFilterorenablePaginationis set (previously footer chrome required pagination).
Docs
- Documentation site rebuilt in the MUI-X layout. The nav is now grouped into labelled sections —
Main features · Server-side data · Components · Customization · Resources — with New and
Coming soon badges. New pages: Cells, Virtualization, Usage, Quick Filter, Styling recipes,
Overlays, Custom subcomponents, Events, State, Performance, plus roadmap stubs (Row grouping, Pivoting,
Columns/Filter Panel). The props reference gained a reading guide (type = possible values · default ·
use-case) and richer per-prop notes. Also fixed a site-wide bug where admonition callouts with a custom
title rendered as literal
:::text.
1.20.0 — 2026-07-10
Backward compatible.
Added
- Labelled toolbar (
toolbarVariant). Toolbar controls default to compact icon-only buttons ('icon', with tooltips). SettoolbarVariant="text"to render each as an icon + label button — clearer for users who don't recognise an icon at a glance. Applies to every built-in control (search, filter, columns, density, export, refresh, reset, saved views, list-view toggle), with the filter count and saved-views "unsaved" dot preserved in both variants. All controls now share oneToolbarButton(standard MUIIconButton/Button), soslots/slotPropsoverrides work the same way in either variant.
Changed
- The bulk-actions bar is now a contextual overlay (Material "contextual app bar" pattern). When a
toolbar is shown, the bar is positioned absolutely over it — edge-to-edge, the same height — so
selecting rows causes zero height change in any mode (the earlier fix stopped it exceeding
maxHeight, but a non-full grid still grew up to the cap; now it doesn't grow at all). When there's no toolbar, the bar renders in flow above the header instead — so it never covers the column headers or the select-all checkbox (matching MUI X / AG Grid, which always keep the header visible). Customslots.bulkActionsToolbarcomponents get the same treatment.
Docs
- The Features nav is grouped into Data · Columns · Rows · Display & layout · Accessibility & i18n (was one long flat list), and the Saved views page — which existed but was never linked — is now in the sidebar.
1.19.0 — 2026-07-10
Adds List view — render rows as full-width list items instead of a columnar table, great for narrow /
mobile layouts (a Pro-only feature in MUI X, free here) — and fixes a maxHeight scroll bug. Backward
compatible.
Fixed
maxHeightno longer double-scrolls when a selection bar appears. The height bound now sits on the root (not the scroll viewport), so all chrome — toolbar, the bulk-actions bar, footer — lives inside the budget and the body flexes. Selecting rows shrinks the body instead of growing the whole grid (and it grows back on clear — no fixed reduced height, no empty space, no second scrollbar). Matches how MUI X / AG Grid bound the container and flex the body.height/100%modes were already correct.
Added
- List view. Set
listView+renderListItemto render each row as one full-width item you fully control (avatar, text, actions, …). The engine is unchanged — sorting, filtering, pagination, selection, saved views, and virtualization all keep working; only the row rendering switches.renderListItem({ row, rowNode, api, index, isSelected })owns the row content.enableListViewadds a built-in grid ⇄ list toggle to the toolbar; control it yourself withlistView+onListViewChange. The classic responsive pattern islistView={isMobile}.- New
rowHeightprop (fixed px, overrides the density row height). - Themeable:
styleOverrides.listItem,slots.listItem/slotProps.listItem, plusslots.gridViewIcon/slots.listViewIcon/slots.viewModeTogglefor the toggle. - Column-only concepts (headers, resize / reorder / pinning, grouped headers, the aggregation footer) turn
off in list view; sort / filter run through the toolbar and
api. See List view.
1.18.3 — 2026-07-09
Deeper MUI-theme integration for typography and spacing, plus roomier cells. No API changes; the grid now follows a custom theme's fonts and spacing.
Changed
- Typography follows the theme. Data cells use
theme.typography.body2and header / aggregation cells usetheme.typography.subtitle2(family, weight, line-height, letter-spacing) — the hardcodedfontSize: 0.8125rem/fontWeight: 600are gone. Font size stays density-scaled via the--dt-font-sizetoken, which now derives fromtheme.typography.body2.fontSize. Applied directly on the styled cell/header primitives — no extra<Typography>wrappers. Side effect: the header font now scales with density (it was previously pinned at the compact size). - Spacing follows
theme.spacing(). Density presets express cell padding — and the toolbar / footer gaps — in spacing units, so--dt-cell-padding-*and the built-in gaps track a customtheme.spacing. - Roomier cells with vertical padding. Cells gained density-based top/bottom padding, and the padding
was retuned to be near-square and more generous (default theme: compact ≈ 8/6px, standard 16px, comfortable
20px, horizontal × vertical). Wrapped or tall content now gets proper breathing room and the row grows with
it instead of the text touching the row edges.
rowHeightstays a min floor, so ordinary single-line rows keep a consistent density height.
Notes
- The
--dt-*tokens remain the fast per-instance /sxoverride channel — they just default fromtheme.spacing/theme.typographynow instead of hardcoded values. Colours and radius were already theme-derived. The div render layer is unchanged: it is 18styled('div', { name, slot })MUI primitives (themeable viastyleOverrides), not raw divs — only three intentional 0-height spacers remain plain.
1.18.2 — 2026-07-09
Fixed
- Header text contrast. The header text colour now derives from
palette.text.primary(wastext.secondary) for a darker, higher-contrast header. Override viapalette.tanstackDataGrid.headerColoror the--dt-header-colorvariable.
1.18.1 — 2026-07-08
Column-header/separator polish and a clearer, safer toolbar Reset. Builds on 1.18.0.
Fixed
- Column separators are a single divider (no more double line). Removed the header cell's box-shadow separator that doubled up with the resize handle. Each resizable column now shows one full-height divider at its trailing edge — subtle (border colour) at rest, accented and thicker on hover / while resizing — and it's still the resize grab area (double-click auto-fits).
- Pinned columns no longer show a broken "dashed" separator. With the header box-shadow gone, a pinned column (e.g. the selection / checkbox column) reads cleanly with just its soft pinned-edge shadow instead of a header sharp line that didn't line up with the body.
Changed
- Roomier cells. Standard (medium) density cell padding is now 16px (was 12px) on header and body cells, matching the MUI reference spacing. Compact (8px) and comfortable (16px) are unchanged.
- "Reset" is now "Reset layout" and resets layout only. The reset button restores the column layout
(
columnOrder+columnPinning+columnSizingby default) and no longer wipes filters, sorting, or pagination, nor reloads the data — a behaviour change from 1.18.0. Widen it with the newresetActionsprop (add'columnVisibility'/'rowPinning'/'filters'/'sorting'/'pagination'), or call it imperatively viaapi.layout.reset(actions?). The old "reset everything + reload" is still available asapi.layout.resetAll(). The refresh button is relabelled "Refresh data" and continues to re-fetch data only (callsonFetchDatain server mode).
Docs
- Props → Toolbar and Toolbar document
resetActionsand the layout-only Reset semantics.
1.18.0 — 2026-07-08
Three things: makes the slots / slotProps / sx customization surface honest (declared parts that
the render layer never read now genuinely apply), polishes the default column header and toolbar to match
the MUI DataGrid reference, and adds support for MUI 8 & 9. Backward compatible — MUI 5/6/7 keep working
unchanged.
Compatibility
- MUI 8 & 9 support. The
@mui/material/@mui/icons-materialpeer range now spans^5 || ^6 || ^7 || ^8 || ^9. The one icon that MUI 8/9 dropped —@mui/icons-material/DeleteOutline(the standalone outline variant), used by the saved-views delete button — is replaced with the standardDeleteOutlinedtheme variant (visually identical, present in every@mui/icons-materialv5–v9). This fixes the Vite build errorFailed to resolve import @mui/icons-material/DeleteOutlineon MUI 9. Verified end-to-end against MUI 9.2.0 (install, icon resolution, SSR render, and a stricttscpass of the grid's component API).
Fixed
- Root
sxandslotProps.rootwere never applied. The root rendered with onlyclassName, silently droppingsx,slotProps.root, and even the caller's ownclassNamewhen combined. All three now apply and merge — the--dt-*design tokens and scroll-layout height can no longer be clobbered by an injectedstyle, and nestedsxarrays flatten correctly. - ~20 dead
slots/slotPropskeys are now wired.scroller,grid,header,headerRow,headerCell,body,row,cell,detailPanel,footer,loadingOverlay,noRowsOverlay, and every toolbar control (searchInput,columnFilterControl,columnVisibilityControl,densityControl,viewsControl,exportButton,refreshButton,resetButton, plus thetoolbarcontainer) are read by the render layer. Structural parts spread your props under their required roles/refs/keyboard wiring (never clobbered); leaf controls take your props last (overrides win). - Resize handle is no longer a full-height bar. The column resize divider is now a short, vertically centered line (like MUI's column separator) — invisible at rest, revealed on header hover, and highlighted while you hover the handle or actively resize. The full-height area remains grabbable (and double-click still auto-fits).
Changed
- Column header layout matches MUI. The title and sort icon now grow to fill the cell, so the per-column
⋮ menu is pinned to the trailing (right) edge instead of sitting next to the label. Alignment
(
left/center/right) is preserved. - Sort affordance on hover. Sortable columns now show a faint sort arrow when you hover the header (previously the arrow appeared only once a column was sorted), so it's discoverable that the column sorts. A sorted column still shows its solid up/down arrow.
- Toolbar is left-aligned. All built-in controls now sit together on the leading edge in a stable order
— search, saved views, filter, columns, density, export, then refresh / reset — mirroring the MUI DataGrid
toolbar. Only the caller-provided
extraFilterslot stays on the trailing edge. - The no-rows overlay's emitted class is now
MuiTanstackDataGrid-noRowsOverlay(was-overlay), matching the documentedstyleOverrides.noRowsOverlaykey.loadingOverlay,grid, andpaginationgained their ownstyleOverridesslots. slots.columnPinningControlis deprecated — it was never read. Column pinning lives in the Columns panel (columnVisibilityControl) and the per-column header ⋮ menu; drive it programmatically viaapiRef.current.columnPinning.
Docs
- Theming → Per-instance overrides and Props → Slots & slotProps now show a
working
sx+slotPropsexample and document the merge semantics (yours wins per-property; required behavior props are protected).
1.17.1 — 2026-06-21
Fixed
- Select/boolean editors in whole-row edit mode wouldn't open — the dropdown was rendered with a
controlled
open={false}, so clicking it did nothing. It's now uncontrolled in row mode (click to open, pick to buffer, Save commits with the row). The Editing row-mode example now shows aselectcolumn end-to-end.
1.17.0 — 2026-06-21
Editing gains whole-row mode and custom editors. Backward compatible (editMode defaults to 'cell').
Added
- Whole-row edit mode. Set
editMode="row"and a row's editable cells open together with explicit Save / Cancel in the actions column (auto-added — no wiring needed);processRowUpdatefires once per row with the fully-updated row. Start via double-click / Enter /apiRef.current.editing.startRowEdit(id);onRowEditStart/onRowEditStopcallbacks; the actions are also exported ascreateRowEditActionto mix with your owngetRowActions. - Custom cell editors.
columnDef.editComponentnow actually drives the inline editor (it was previously dead). It receivesDataTableEditComponentProps(value/onChange/onCommit/onCancel/row/column/align/editMode) and works in both cell and row mode.
Changed
columnDef.editComponentis no longer a fallback for the column filter input — usefilterComponentfor that. (No known consumers relied on the fallback.)
Docs
- Editing documents row mode, the
editComponenteditor, andapiRef.current.editing.
1.16.1 — 2026-06-21
Inline-editing fixes + much fuller docs.
Fixed
- Nested-key edits. Committing an edit to a dot-nested
accessorKey(e.g.address.city) now deep-sets the nested field instead of creating a stray flat"address.city"key, so the change actually takes effect. NewsetNestedValueutil (immutable, clones only along the path). - Editor UI. Dropped the inline editor's underline (it rendered as a stray line across the middle of the cell); the cell now shows a clean full-cell ring while editing.
Docs
- Editing is rewritten to cover getting the updated data (
processRowUpdate), which field is written (accessorKey / nested keys / row identity), server-side persistence, validation, the imperativeapiRef.current.dataAPI, and the type-aware editors.
1.16.0 — 2026-06-21
Last remaining backlog slice — two rendering-correctness fixes. Backward compatible.
Added
- Right-to-left (RTL). Set
direction: 'rtl'on your theme and the grid mirrors itself — pinned columns flip side, the resize handle and sort/⋮-menu move to the logical edge, text aligns to the start, and tree indentation + column separators mirror. The grid setsdir="rtl"on its root, so it works with no extra setup. See Theming → RTL.
Fixed
- Grouped (multi-level) headers now align correctly: a group header spans its leaf columns' combined
width and lines up with the leaf row and body cells (previously they could drift under
fitToScreen). Group headers carry no sort/resize/⋮-menu, only the leaf header row takes keyboard focus, andaria-rowindex/aria-rowcount/aria-colspanaccount for the extra header rows. See Columns → Grouped headers.
Docs
1.15.0 — 2026-06-21
Third remaining backlog slice. Backward compatible.
Added
- Saved / named views.
enableSavedViewsadds a toolbar Views control that captures the current layout (search, filters, sort, column visibility/order/width, pinning, density, page size) as a named preset the user can switch between, update, and delete. A dot marks unsaved changes against the active view. Stored underdt:<stateKey>:views(uncontrolled) or driven viaviews/onViewsChange/activeViewId/onActiveViewChange(controlled). FullapiRef.current.viewsnamespace (saveView/applyView/updateView/renameView/deleteView/resetView/listViews/getActiveView/isDirty) and aviewsIconslot.
Changed
apiRef.current.layout.saveLayout()/restoreLayout()now also capture and restore sorting and density (so a layout snapshot — and a saved view — round-trips the full user-visible layout).
Docs
- New Saved views page with a live demo.
1.14.0 — 2026-06-21
Second remaining backlog slice. Backward compatible.
Added
- Row pinning. Pin individual rows to the top and/or bottom so they stay visible while the
rest scroll — pinned rows survive sort, filter, and pagination. Enable with
enableRowPinning; seed withinitialState.rowPinning; pin viaapiRef.current.rowPinning(pinRowTop/pinRowBottom/unpinRow/setRowPinning/resetRowPinning/getPinnedRowIds) or the exportedcreateRowPinActionhelper (spread intogetRowActions). FiresonRowPinningChange; included insaveLayout/restoreLayout. Client data mode only (ignored under server pagination); top-level rows only (not tree sub-rows). Persist withpersist.include: ['rowPinning']plus a stablegetRowId.
Docs
- Pinning gains a "Row pinning" section + live demo.
1.13.0 — 2026-06-21
First of the remaining backlog slices. Backward compatible.
Added
- Column header menu. Each column header gains a quiet ⋮ menu (revealed on hover or keyboard
focus) that surfaces the actions already wired into the grid — sort ascending/descending/clear,
autosize this column (needs
enableColumnResizing), and hide column (needsenableColumnVisibility). It only lists available actions (none → no kebab), marks the active sort, disables redundant items, and won't hide the last visible column. Keyboard: focus a header and press Enter. On by default —enableColumnMenu={false}removes it table-wide,disableColumnMenu: trueper column; swap the glyph withslots.columnMenuIcon.
Changed
- With the column menu on (the default), pressing Enter on a focused sortable header now opens its
column menu instead of toggling the sort directly (the menu's first item is Sort ascending).
Mouse-clicking the header still toggles sort. Set
enableColumnMenu={false}to restore the old behavior.
Docs
- Columns gains a "Column menu" section + live demo.
1.12.0 — 2026-06-21
More admin power-user features from the deferred backlog. Backward compatible.
Added
- Configurable page size.
rowsPerPageOptionssets the footer's page-size choices (default[5, 10, 25, 50, 100];[]hides the selector). Replace the whole footer withslots.pagination. - Faceted (auto) filter options. A
type: 'select'column with nooptionsauto-populates its filter values from the data's distinct values (cardinality-guarded). Values reflect the data, not other active filters. - Clipboard copy.
enableClipboardCopyadds a Copy action to the bulk-actions bar (tab-separated text that pastes into Sheets/Excel); alsoapiRef.current.clipboard.copySelectedRows()and theonClipboardCopy(count)callback.
Docs
- Pagination (page-size options), Filtering (auto-populated options), and Selection (clipboard copy) each gain a section + live demo.
1.11.1 — 2026-06-21
Fixed
- Client-mode counts now respect active filters. When filtering client-side, the pagination footer
("of N"),
aria-rowcount, the select-all / exclude-mode count, and the last-page math used the unfiltered total. They now reflect the filtered (pre-pagination) row count. Server mode, therowCounttable option, and the export pipeline are unchanged.
1.11.0 — 2026-06-20
Polishes the Tier C features — the documented follow-ups. Backward compatible.
Added
- Screen-reader announcements. A visually-hidden
aria-liveregion announces sort, filter, page, and selection changes (localizable:announceSort,announceFilteredRows,announcePage,selectedRows). - Persistable tree expansion. Add
'expanded'topersist.includeto remember which tree rows are expanded across reloads (opt-in; still excluded by default).
Fixed
- Column filters are now tree-aware. A branch is kept when it or any descendant matches, so a matching child is no longer dropped because its parent doesn't match (previously filters were top-level-only). The kept branch shows in full.
Docs
- Accessibility documents the live-region announcer; Tree data documents tree-aware filtering and expansion persistence.
1.10.0 — 2026-06-20
Completes Tier C — keyboard accessibility, inline editing, and tree data. Backward compatible (no API removed); the grid now uses the ARIA grid roles and keyboard nav is always on.
Added
- Keyboard navigation + ARIA grid. WCAG grid-pattern operability:
role="grid"(treegridfor tree data),aria-rowindex/aria-colindex/aria-rowcount/aria-colcount, headeraria-sort. A roving tabindex with ↑ ↓ ← →, Home/End, Ctrl+Home/End, PageUp/PageDown moves the focused cell; Enter/F2 activates it (sort a header, toggle a control, or start editing); focus follows paging and scrolls virtualized rows into view. See Accessibility. - Inline cell editing. Mark a column
editable; double-click or Enter/F2 to edit. Type-aware editor (text / number / date, dropdown forselect/boolean); Enter or blur commits, Escape cancels.processRowUpdate(newRow, oldRow)persists the change (reverts +onProcessRowUpdateErroron a throw); without it, edits update the grid's local data. - Tree data.
getSubRowsrenders hierarchical rows — an expander only on rows with children, depth indentation, androle="treegrid"+aria-level/aria-expanded. Use instead ofrenderDetailPanel.
Changed
- The scroll container is now
role="grid"(wasrole="table") and body cellsrole="gridcell", per the ARIA grid pattern.
Docs
- New Accessibility, Editing, and Tree data feature pages, each with a live demo.
Finishes Tier B — a footer aggregation row and full localization. Backward compatible.
Added
- Footer aggregation.
enableAggregation+ a per-columnaggregation('sum' | 'avg' | 'min' | 'max' | 'count', or a function over the filtered rows) renders a sticky footer summary row, aligned with and pinned like its columns. Totals also available viaapiRef.current.aggregation.getTotals(). Client mode (server/grouped totals out of scope). - Localization —
localeText. Every built-in string — operator labels, toolbar tooltips, the column-filter and columns panels, the selection count, "No rows", pagination labels, and aria-labels — is translatable via a partiallocaleText(unset keys fall back to English). Operator labels localize while the underlying operator value (the logic key) is unchanged. The English bundle is exported asenUS/DEFAULT_LOCALE_TEXT; interpolated strings (selectedRows,paginationDisplayedRows) are functions.
Docs
- New Aggregation and Localization feature pages, each with a live demo (a summary row; an EN↔FR toggle).
1.8.0 — 2026-06-20
Tier B CRUD verbs — a row-actions column and value getters / formatters, the two features that remove the most per-column boilerplate. Backward compatible.
Added
- Row actions.
getRowActions(row) => DataTableRowAction[]adds an auto-generated_actionscolumn (pinned right whenenableColumnPinningis on). A few actions render as inline icon buttons; 3+ (or any without anicon) collapse into an overflow ⋮ menu. Each action is{ label, icon?, onClick(row), disabled?, hidden?, color? }. Configure viaslotProps.actionsColumn,rowActionsDisplay('icons' | 'menu' | 'auto'), andslots.moreActionsIcon. Handlers stop propagation so they don't triggeronRowClick. column.valueGetter— derive a value for a column with noaccessorKey; it compiles to a TanStackaccessorFn, so sorting, filtering, and export all read the derived value.column.valueFormatter— format a value for display only (export keeps the raw value).- Type-default cells. A column's
type(number/date/boolean/select) now renders a sensible default cell — locale-grouped number,dayjs-formatted date (no UTC drift), Yes/No, or the matchingoptionslabel — when you don't supply acell. Precedence:cell>valueFormatter> type default > raw.
Docs
- Columns gains Value getters & formatters and Row actions sections, each with a live demo.
1.7.0 — 2026-06-20
Makes the public API honest — turns several typed-but-dead props/methods into working features and adds a range filter operator. Backward compatible: every new hook is opt-in and unset behaves exactly as before.
Added
column.wrapText— wrap long cell (and header) text instead of truncating with an ellipsis. In non-virtualized grids the CSS-Grid rows grow to fit for free.column.cellClassName—stringor({ value, row }) => stringapplied to each body cell of the column (DataGrid-style conditional styling).column.headerClassName—stringapplied to the column's header cell.getRowClassName({ row, index })— table-level hook to class each row.getCellClassName({ row, columnId, value })— table-level hook to class each cell; merges with the per-columncellClassName.betweenfilter operator (number & date) in the column-filter rule builder — a two-field{ from, to }range; either bound may be omitted (open-ended). Inclusive.
Fixed
autoSizeColumn/autoSizeAllColumnsnow work (apiRef.columnResizing.*) — they were no-ops. Double-click a column's resize handle to fit it to its content; widths clamp to the column'sminSize/maxSizeand persist like a manual resize. (Measures the rows currently in the DOM — the virtual window / current page.)- Resized / auto-fitted columns hold their exact width under
fitToScreen. Previously a column you resized still flex-grew to fill, so its width drifted; now a user-sized column keeps its width while the remaining (untouched) columns absorb spare space.
Docs
- Columns gains a Cell & row styling section with a live demo of
wrapTextand the class-name hooks, and a note on double-click auto-fit. The Filtering page documents thebetweenrange operator.
wrapText grows rows in the standard (non-virtualized) grid. Under enableVirtualization the virtualizer
uses a fixed row-height estimate, so wrapped rows are clipped to the estimate; per-row measurement for
virtualized auto-height is a separate, future enhancement.
1.6.1 — 2026-06-19
Fixes the height / sticky / scroll behaviour and gives it a proper, standard model — the grid is now a
flex column with three height modes (Height & scrolling). Backward compatible:
auto-height and existing stickyHeader / maxHeight setups are unchanged.
Fixed
stickyFooternow works. It was declared but never wired; it now pins the footer and bounds the body likestickyHeader.maxHeightis active on its own. Previously it was ignored unlessstickyHeader(orenableVirtualization) was also set; settingmaxHeightnow caps and scrolls by itself.enableStickyHeaderOrFooter(the deprecated alias) is honored again — it maps tostickyHeader.- The grid root is a flex column and the scroller flexes (
flex: 1 1 auto; min-height: 0), so in a fixed/fill height the footer correctly pins to the bottom while the body scrolls.
Added
height— fix the grid height ('100%'fills a sized parent); the body flexes to fill and scrolls while the header and footer stay pinned (the dashboard-panel layout that wasn't previously expressible).minHeight— optional floor so a near-empty grid doesn't collapse. A bounded height is not required for the body to scroll; this is purely a minimum.
Docs
- New Height & scrolling feature page with a live demo of each mode. The example app's
Layout page was rewritten around the three modes (it previously documented a removed
TableContainerAPI).
1.6.0 — 2026-06-19
Added
clearPersistedState(stateKey, persist?)— forget a grid's saved view (for a "reset saved view" button); pair it with a remount/reload to start frominitialState. SSR-safe.
Docs
- Live dark-mode and persistence demos. The
1.5.0
cssVariablesdark-mode and persistence features were verified end-to-end (grid follows the scheme toggle; state survives a reload).
1.5.0 — 2026-06-17
Integration-quality improvements for teams building on top of <DataTable>.
Added
- State persistence. Set
stateKey="…"to remember pagination, sort, search, filters, and column layout (order / width / visibility / pinning) + density across reloads and remounts — no extra wiring. Tune withpersist?: { storage?: 'local' | 'session' | StorageLike; include?: (keyof TableState)[]; debounceMs?: number }. Selection + expansion are excluded by default; SSR-safe. defaultDensity. An uncontrolled initial density (also honorsinitialState.density) so you can set a starting density without disabling the density selector.densityremains the controlled override.- Type re-exports. The TanStack types used across the public surface —
ColumnPinningState,SortingState,ColumnOrderState,VisibilityState,ColumnSizingState,PaginationState,ExpandedState,RowSelectionState,Row,ColumnDef,Updater— are now exported from the package root, so callbacks/state type without deep imports.
Fixed
- Density selector no longer dead when a default is set. Passing
densitypreviously pinned it (the selector became a no-op). UsedefaultDensity/initialState.densityfor a changeable start. - Dark mode under MUI
cssVariables. The grid now reads colours viatheme.varsand emits its mode-dependent defaults withapplyStyles('dark'), so it followscolorSchemestoggling.createDataTableTheme()emits per-schemecolorSchemesoverrides (with an optionaldarkPalette) instead of a flat top-levelpalette, composing cleanly with acssVariablesapp theme.
1.4.3 — 2026-06-16
Fixed
- Pagination footer survives CSS-heavy host pages. Completes the 1.4.2 fix. Global
p { margin }from host typography (Docusaurus, WordPress themes, Tailwind/Bootstrap resets) was leaking into MUI's pagination<p>labels and ballooning the footer to ~3× height (and 1.4.2'sflex-wrapthen made it wrap). The labels are now pinned flush (margin: 0) and the pagination root spans the full width, so the footer stays a clean single row wherever the grid is embedded — not just in a pristine MUI app.
1.4.2 — 2026-06-16
Fixed
- Pagination footer layout. Tamed MUI's
TablePaginationinside the grid: its padding now aligns with the cells (was cramped against the right edge), it no longer renders a private horizontal scrollbar (overflow: auto), and it wraps gracefully on narrow widths instead of overflowing the rounded card.
1.4.1 — 2026-06-16
Fixed
- Pinned columns now keep column order. Pinning a column right no longer appends it past the others — each side renders in the columns' order, so e.g. a last "Actions" column stays rightmost when you pin another column right.
- Default-pinned special columns survive a custom
initialState. The automatic left-pin of the selection / expander columns now merges withinitialState.columnPinninginstead of being replaced, so pinning your own columns (e.g.right: ['actions']) no longer un-pins the checkbox/expander. Override by pinning a special column yourself.
1.4.0 — 2026-06-16
A design-reference visual refresh, a full column manager, and a customizable toolbar.
Added
renderToolbarrender-prop — arrange the built-in toolbar controls (search, filter, columns, density, export, refresh, reset,extraFilter) in any order or position.slots.toolbaris now also wired for a complete replacement. See Toolbar → Reorder / reposition.- Rebuilt Columns panel (the toolbar ⊞ button): wider + compact, with a per-column show/hide eye toggle, pin left/right, drag-to-reorder, and a Show all / Reset / Done footer. Replaces the old checkbox menu. See The Columns panel.
- Feather-style default icons for the toolbar and sort indicators — lightweight inline SVG (no
@mui/icons-materialbarrel pulled in), still fully overridable throughslots.
Changed
- Default look refreshed to match the design reference: header uses
text.secondarylabels at 13px with subtle column separators. DataTableSlotsreorganized — kept flat (MUI-consistent) but grouped by section, and the permissive[slot: string]index signature was removed so you get real autocomplete + typo-safety.slotPropsnow explicitly typesselectionColumn/expandColumn. (If you were passing an unknown slot key, TS will now flag it.)
Docs
- Confirmed light + dark theme support end-to-end, including under
CssVarsProvider— every colour derives from your MUI theme and follows a light↔dark switch automatically. - New: toolbar reorder demo, Columns-panel guide, and a grouped Slots reference.
1.3.3 — 2026-06-15
Column pinning gets a UI, and row expansion now actually works.
Added
- Column pinning controls. The toolbar's Columns menu now has per-column pin-left / pin-right toggles (next to the visibility checkbox). Click an active side to unpin.
- Default-pinned special columns. When
enableColumnPinningis on, the selection (_selection) and expander (_expanding) columns pin to the left automatically so they stay visible while scrolling. Override viainitialState.columnPinning. - New docs: Column pinning and Row expansion.
Fixed
- Row expansion now renders.
renderDetailPanelwas previously declared but never drawn (the expand chevron toggled state but showed nothing). The grid now registers the expanded row model, renders the detail panel beneath an expanded row, and defaults every row to expandable (gate withgetRowCanExpand).
1.3.2 — 2026-06-15
A modern default look for the grid and toolbar — all still fully overridable via the same
theme/token/slotProps layers.
Added
- Self-framing card. The grid now renders inside a rounded, bordered surface (it finally consumes
the
--dt-radiustoken, floored at 8px). No need to wrap it in your own<Paper>. - Collapsible search. The global search is now a search icon that expands into a field on click (auto-focus, clear button, auto-collapses when emptied) instead of an always-on input.
- Themeable
Toolbarslot (components.MuiTanstackDataGrid.styleOverrides.toolbar). - Selected rows now get a background tint (
--dt-row-bg-selected); rows transition smoothly on hover.
Changed
- Full-width by default.
fitToScreennow defaults totrue, so columns stretch to fill the container (they still never shrink below their defined size — wide tables scroll). PassfitToScreen={false}for the previous fixed-width behaviour. - Modernized dropdowns. Density, columns and export menus get rounded/elevated surfaces, section labels, and the density menu shows a per-option icon + a check on the active density.
extraFiltermoved to the right side of the toolbar (was on the left).- Default header is crisper:
text.primarylabels on a lightergrey[50](light) background; the striped path now uses the dedicated--dt-row-bg-stripetoken.
Docs
- Updated Theming defaults table and Toolbar (collapsible search,
extraFilterplacement, the newtoolbarstyle slot).
1.3.1 — 2026-06-15
Documentation/metadata corrections only — no API or runtime changes.
Fixed
- Corrected a stale banner comment in the published type declarations (
dist/types/index.d.ts) that still described the package as a "Phase 1 scaffold" with the grid components "landing in later phases." It now accurately reflects the shipped surface (and the correct package name).
Docs
- Migration guide: documented the v1 → v2 imperative-handle change — the
forwardRefrefis replaced by anapiRefprop (the API itself is unchanged). Clarified thatstateKey/defaultHiddenColumnswere example-wrapper props, never grid props.
1.3.0 — 2026-06-14
Dual-format build so bundlers tree-shake unused grid code (not just icons).
Added
- Dual ESM + CommonJS output.
importresolves to the ESM build,require()to the CommonJS build, via the packageexportsmap. Works in Vite, webpack, Rollup, esbuild, Next.js, and plain Node. "sideEffects": false— bundlers drop any feature you don't import (importing a single helper now pulls ~200 bytes instead of the whole grid).- TypeScript declarations shipped under
dist/types.
Changed
- Build split into separate CJS / ESM / types passes; ESM relative imports are emitted fully-specified
(
./x.js) so strict resolvers (webpack, Rspack, Next.js, Node native ESM) resolve them.
Docs
- New Bundle size & module formats section in Getting Started; build + module notes added to the package README.
1.2.0 — 2026-06-14
Smaller bundles and customizable icons.
Fixed
- Icons are imported per-path (
@mui/icons-material/Search) instead of from the barrel. Consumers no longer bundle the full ~2,100-icon set — no alias or shim needed. (A build test now guards against this regressing.)
Added
- Per-icon
slotsso you can supply your own icon set (lucide, custom SVGs, a different MUI variant):searchIcon,filterIcon,addFilterIcon,clearIcon,columnsIcon,densityIcon,exportIcon,refreshIcon,resetIcon,expandIcon,collapseIcon, plus the now-wiredsortIconAsc/sortIconDesc. Each defaults to the matching MUI icon. - Sort indicators are sized via CSS, so a custom non-MUI icon renders without React unknown-prop warnings.
Docs
- New Custom icons section in Toolbar.
1.1.0 — 2026-06-13
First public release on npm. Large-data export overhaul.
Added
- Four export modes —
client(default),server-data,server-file, andserver-async— sharing oneExportRequestdescriptor that carries the chosen columns, scope (all / filtered / selected), selection, filters, and sorting. - Streaming export (File System Access API with a blob fallback), line-by-line CSV, lazy-loaded XLSX
with the Excel row cap, native
<a download>for file URLs, CSV-injection sanitizing, and cancellation.
Docs
- Rewrote Export and Server-side docs: both server data approaches (
onFetchDatavs controlleddata+rowCount+onDataStateChange) and the exact filter payload shape for mapping to your API.
1.0.1 — 2026-06-13
- Republish of
1.0.0during npm publishing setup — no functional changes.
1.0.0 — 2026-06-13
Initial release of the rebuilt grid — successor to the now-deprecated
@ackplus/react-tanstack-data-table.
Added
<div>/ CSS-Grid rendering (no HTML<table>) for reliable column sizing, resize, and pinning.- Themeable like a MUI component — inherits your MUI theme; override via
components.MuiTanstackDataGrid,--dt-*CSS variables, orsx. - Sorting, global + column filtering, pagination, row selection + bulk actions, column pinning / reordering / resizing, row expansion, and virtualization.
- CSV + lazy Excel export.
- Server-side data support, a
useDataTable()headless hook, andslots/slotPropsfor overriding any part.