Skip to main content

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.x releases are backward compatible. Install a specific version with npm install @ackplus/mui-tanstack-data-grid@<version>.


1.21.2 — 2026-07-25

Backward compatible.

Fixed

  • Nested accessorKey columns no longer misalign. Columns that share a dotted path prefix (e.g. unit.user.firstName and unit.user.lastName) used those ids in CSS width variables (--col-<id>-size). CSS var() 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 onlycolumn.id / filter / sort / server payloads still use the dotted path. No custom id remapping 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 64px min-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), and api.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.columnVisibilityControl hides the item it can't drive (Clear filter still works, since it goes straight through the API). Also hardened clearColumnFilter against 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.main with no override path — no --dt-* token, no styled slot, and the default component dropped slotProps.bulkActionsToolbar. The bar is now a first-class bulkActionsToolbar styled slot whose surface reads two new tokens, --dt-bulkbar-bg / --dt-bulkbar-fg (defaulting from palette.primary.main / palette.primary.contrastText, scheme-aware). Retint it any of three ways — the tokens (sx={{ '--dt-bulkbar-bg': … }}), theme styleOverrides.bulkActionsToolbar, or slotProps.bulkActionsToolbar (its sx / 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

  • selectOnRowClick now 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 (needs enableRowSelection; respects single/multi mode and per-row isRowSelectable). Clicks on the checkbox, row expander, action buttons, or an editing cell don't trigger it (they stop propagation), and it composes with onRowClick — 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 an onRowClick (e.g. one that navigates to a detail page), ticking the box or expanding a row also triggered the row click. They now stopPropagation (matching the actions cell): the checkbox still toggles selection, the button still expands, and clicking a normal cell still fires onRowClick.

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 base size; the instant a resize wrote columnSizing, 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/onEnd modes, touch, and RTL are unchanged.

1.20.1 — 2026-07-11

Backward compatible.

Fixed

  • footerFilter now renders. The prop was declared on DataTableProps (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 how extraFilter sits 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 whenever footerFilter or enablePagination is 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). Set toolbarVariant="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 one ToolbarButton (standard MUI IconButton/Button), so slots/slotProps overrides 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). Custom slots.bulkActionsToolbar components 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

  • maxHeight no 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 + renderListItem to 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.
    • enableListView adds a built-in grid ⇄ list toggle to the toolbar; control it yourself with listView + onListViewChange. The classic responsive pattern is listView={isMobile}.
    • New rowHeight prop (fixed px, overrides the density row height).
    • Themeable: styleOverrides.listItem, slots.listItem / slotProps.listItem, plus slots.gridViewIcon / slots.listViewIcon / slots.viewModeToggle for 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.body2 and header / aggregation cells use theme.typography.subtitle2 (family, weight, line-height, letter-spacing) — the hardcoded fontSize: 0.8125rem / fontWeight: 600 are gone. Font size stays density-scaled via the --dt-font-size token, which now derives from theme.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 custom theme.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. rowHeight stays a min floor, so ordinary single-line rows keep a consistent density height.

Notes

  • The --dt-* tokens remain the fast per-instance / sx override channel — they just default from theme.spacing / theme.typography now instead of hardcoded values. Colours and radius were already theme-derived. The div render layer is unchanged: it is 18 styled('div', { name, slot }) MUI primitives (themeable via styleOverrides), 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 (was text.secondary) for a darker, higher-contrast header. Override via palette.tanstackDataGrid.headerColor or the --dt-header-color variable.

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 + columnSizing by default) and no longer wipes filters, sorting, or pagination, nor reloads the data — a behaviour change from 1.18.0. Widen it with the new resetActions prop (add 'columnVisibility' / 'rowPinning' / 'filters' / 'sorting' / 'pagination'), or call it imperatively via api.layout.reset(actions?). The old "reset everything + reload" is still available as api.layout.resetAll(). The refresh button is relabelled "Refresh data" and continues to re-fetch data only (calls onFetchData in server mode).

Docs


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-material peer 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 standard DeleteOutlined theme variant (visually identical, present in every @mui/icons-material v5–v9). This fixes the Vite build error Failed to resolve import @mui/icons-material/DeleteOutline on MUI 9. Verified end-to-end against MUI 9.2.0 (install, icon resolution, SSR render, and a strict tsc pass of the grid's component API).

Fixed

  • Root sx and slotProps.root were never applied. The root rendered with only className, silently dropping sx, slotProps.root, and even the caller's own className when combined. All three now apply and merge — the --dt-* design tokens and scroll-layout height can no longer be clobbered by an injected style, and nested sx arrays flatten correctly.
  • ~20 dead slots / slotProps keys 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 the toolbar container) 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 extraFilter slot stays on the trailing edge.
  • The no-rows overlay's emitted class is now MuiTanstackDataGrid-noRowsOverlay (was -overlay), matching the documented styleOverrides.noRowsOverlay key. loadingOverlay, grid, and pagination gained their own styleOverrides slots.
  • slots.columnPinningControl is deprecated — it was never read. Column pinning lives in the Columns panel (columnVisibilityControl) and the per-column header ⋮ menu; drive it programmatically via apiRef.current.columnPinning.

Docs


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 a select column 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); processRowUpdate fires once per row with the fully-updated row. Start via double-click / Enter / apiRef.current.editing.startRowEdit(id); onRowEditStart / onRowEditStop callbacks; the actions are also exported as createRowEditAction to mix with your own getRowActions.
  • Custom cell editors. columnDef.editComponent now actually drives the inline editor (it was previously dead). It receives DataTableEditComponentProps (value / onChange / onCommit / onCancel / row / column / align / editMode) and works in both cell and row mode.

Changed

  • columnDef.editComponent is no longer a fallback for the column filter input — use filterComponent for that. (No known consumers relied on the fallback.)

Docs

  • Editing documents row mode, the editComponent editor, and apiRef.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. New setNestedValue util (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 imperative apiRef.current.data API, 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 sets dir="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, and aria-rowindex/aria-rowcount/aria-colspan account for the extra header rows. See Columns → Grouped headers.

Docs

  • New Grouped headers (Columns) and RTL (Theming) sections + live demos.

1.15.0 — 2026-06-21

Third remaining backlog slice. Backward compatible.

Added

  • Saved / named views. enableSavedViews adds 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 under dt:<stateKey>:views (uncontrolled) or driven via views / onViewsChange / activeViewId / onActiveViewChange (controlled). Full apiRef.current.views namespace (saveView / applyView / updateView / renameView / deleteView / resetView / listViews / getActiveView / isDirty) and a viewsIcon slot.

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


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 with initialState.rowPinning; pin via apiRef.current.rowPinning (pinRowTop / pinRowBottom / unpinRow / setRowPinning / resetRowPinning / getPinnedRowIds) or the exported createRowPinAction helper (spread into getRowActions). Fires onRowPinningChange; included in saveLayout/restoreLayout. Client data mode only (ignored under server pagination); top-level rows only (not tree sub-rows). Persist with persist.include: ['rowPinning'] plus a stable getRowId.

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 (needs enableColumnVisibility). 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: true per column; swap the glyph with slots.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. rowsPerPageOptions sets the footer's page-size choices (default [5, 10, 25, 50, 100]; [] hides the selector). Replace the whole footer with slots.pagination.
  • Faceted (auto) filter options. A type: 'select' column with no options auto-populates its filter values from the data's distinct values (cardinality-guarded). Values reflect the data, not other active filters.
  • Clipboard copy. enableClipboardCopy adds a Copy action to the bulk-actions bar (tab-separated text that pastes into Sheets/Excel); also apiRef.current.clipboard.copySelectedRows() and the onClipboardCopy(count) callback.

Docs


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, the rowCount table 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-live region announces sort, filter, page, and selection changes (localizable: announceSort, announceFilteredRows, announcePage, selectedRows).
  • Persistable tree expansion. Add 'expanded' to persist.include to 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" (treegrid for tree data), aria-rowindex/aria-colindex/aria-rowcount/aria-colcount, header aria-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 for select/boolean); Enter or blur commits, Escape cancels. processRowUpdate(newRow, oldRow) persists the change (reverts + onProcessRowUpdateError on a throw); without it, edits update the grid's local data.
  • Tree data. getSubRows renders hierarchical rows — an expander only on rows with children, depth indentation, and role="treegrid" + aria-level / aria-expanded. Use instead of renderDetailPanel.

Changed

  • The scroll container is now role="grid" (was role="table") and body cells role="gridcell", per the ARIA grid pattern.

Docs

Finishes Tier B — a footer aggregation row and full localization. Backward compatible.

Added

  • Footer aggregation. enableAggregation + a per-column aggregation ('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 via apiRef.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 partial localeText (unset keys fall back to English). Operator labels localize while the underlying operator value (the logic key) is unchanged. The English bundle is exported as enUS / DEFAULT_LOCALE_TEXT; interpolated strings (selectedRows, paginationDisplayedRows) are functions.

Docs


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 _actions column (pinned right when enableColumnPinning is on). A few actions render as inline icon buttons; 3+ (or any without an icon) collapse into an overflow menu. Each action is { label, icon?, onClick(row), disabled?, hidden?, color? }. Configure via slotProps.actionsColumn, rowActionsDisplay ('icons' | 'menu' | 'auto'), and slots.moreActionsIcon. Handlers stop propagation so they don't trigger onRowClick.
  • column.valueGetter — derive a value for a column with no accessorKey; it compiles to a TanStack accessorFn, 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 matching options label — when you don't supply a cell. 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.cellClassNamestring or ({ value, row }) => string applied to each body cell of the column (DataGrid-style conditional styling).
  • column.headerClassNamestring applied 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-column cellClassName.
  • between filter 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 / autoSizeAllColumns now 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's minSize/maxSize and 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 wrapText and the class-name hooks, and a note on double-click auto-fit. The Filtering page documents the between range operator.
Virtualization + auto-height

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

  • stickyFooter now works. It was declared but never wired; it now pins the footer and bounds the body like stickyHeader.
  • maxHeight is active on its own. Previously it was ignored unless stickyHeader (or enableVirtualization) was also set; setting maxHeight now caps and scrolls by itself.
  • enableStickyHeaderOrFooter (the deprecated alias) is honored again — it maps to stickyHeader.
  • 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 TableContainer API).

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 from initialState. SSR-safe.

Docs

  • Live dark-mode and persistence demos. The 1.5.0 cssVariables dark-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 with persist?: { storage?: 'local' | 'session' | StorageLike; include?: (keyof TableState)[]; debounceMs?: number }. Selection + expansion are excluded by default; SSR-safe.
  • defaultDensity. An uncontrolled initial density (also honors initialState.density) so you can set a starting density without disabling the density selector. density remains 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 density previously pinned it (the selector became a no-op). Use defaultDensity / initialState.density for a changeable start.
  • Dark mode under MUI cssVariables. The grid now reads colours via theme.vars and emits its mode-dependent defaults with applyStyles('dark'), so it follows colorSchemes toggling. createDataTableTheme() emits per-scheme colorSchemes overrides (with an optional darkPalette) instead of a flat top-level palette, composing cleanly with a cssVariables app 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's flex-wrap then 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 TablePagination inside 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 with initialState.columnPinning instead 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

  • renderToolbar render-prop — arrange the built-in toolbar controls (search, filter, columns, density, export, refresh, reset, extraFilter) in any order or position. slots.toolbar is 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-material barrel pulled in), still fully overridable through slots.

Changed

  • Default look refreshed to match the design reference: header uses text.secondary labels at 13px with subtle column separators.
  • DataTableSlots reorganized — kept flat (MUI-consistent) but grouped by section, and the permissive [slot: string] index signature was removed so you get real autocomplete + typo-safety. slotProps now explicitly types selectionColumn / 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 enableColumnPinning is on, the selection (_selection) and expander (_expanding) columns pin to the left automatically so they stay visible while scrolling. Override via initialState.columnPinning.
  • New docs: Column pinning and Row expansion.

Fixed

  • Row expansion now renders. renderDetailPanel was 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 with getRowCanExpand).

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-radius token, 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 Toolbar slot (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. fitToScreen now defaults to true, so columns stretch to fill the container (they still never shrink below their defined size — wide tables scroll). Pass fitToScreen={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.
  • extraFilter moved to the right side of the toolbar (was on the left).
  • Default header is crisper: text.primary labels on a lighter grey[50] (light) background; the striped path now uses the dedicated --dt-row-bg-stripe token.

Docs

  • Updated Theming defaults table and Toolbar (collapsible search, extraFilter placement, the new toolbar style 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 forwardRef ref is replaced by an apiRef prop (the API itself is unchanged). Clarified that stateKey / defaultHiddenColumns were 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. import resolves to the ESM build, require() to the CommonJS build, via the package exports map. 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 slots so 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-wired sortIconAsc / 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


1.1.0 — 2026-06-13

First public release on npm. Large-data export overhaul.

Added

  • Four export modesclient (default), server-data, server-file, and server-async — sharing one ExportRequest descriptor 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 (onFetchData vs controlled data + rowCount + onDataStateChange) and the exact filter payload shape for mapping to your API.

1.0.1 — 2026-06-13

  • Republish of 1.0.0 during 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, or sx.
  • 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, and slots / slotProps for overriding any part.