Skip to main content

Theming

The grid themes like a MUI component, and your MUI theme is the single source of truth — set colours once and the grid follows. The override surface mirrors MUI X DataGrid.

1. Inherits your MUI theme

Out of the box, colours, typography, spacing, radius, dark mode, and RTL all come from your app's ThemeProvider. No setup needed.

2. Theme it like a MUI component

Register palette.tanstackDataGrid and components.MuiTanstackDataGrid in createTheme — exactly like MuiButton or MuiDataGrid:

import { createTheme } from '@mui/material/styles';

const theme = createTheme({
// colours once, in the palette (defaults derive from the base palette)
palette: {
tanstackDataGrid: { headerBg: '#eef2ff', headerColor: '#4338ca', borderColor: '#e0e7ff' },
},
components: {
MuiTanstackDataGrid: {
defaultProps: { density: 'compact', striped: true },
styleOverrides: {
header: { textTransform: 'uppercase', letterSpacing: '0.04em', fontSize: 11 },
cell: { borderRight: '1px solid var(--dt-border-color)' },
row: { '&:hover': { '--dt-row-bg': '#f5f3ff' } },
},
},
},
});

The grid below is the same one, rendered under that theme:

Loading demo…

3. Design tokens (CSS variables)

Every visual is a --dt-* CSS variable whose default derives from your MUI theme. Override a token only to make the grid deviate from the rest of the app.

The grid renders as a self-framing card — a 1px --dt-border-color outer border with --dt-radius rounded corners — so you don't need to wrap it in your own <Paper>. Drop the frame with sx={{ border: 0, borderRadius: 0 }} on the root if you prefer.

TokenDefaults from
--dt-border-colorpalette.divider
--dt-header-bgpalette.grey[50] (light) / palette.grey[900] (dark)
--dt-header-colorpalette.text.secondary
--dt-row-bg-hoverpalette.action.hover
--dt-row-bg-selectedpalette.action.selected
--dt-row-bg-stripesubtle tint (used when striped)
--dt-row-height, --dt-cell-padding-x/ydensity preset
--dt-font-sizedensity preset
--dt-radiustheme.shape.borderRadius (floored at 8px)

4. Per-instance overrides

Use the density prop, sx on the root, or slotProps on any part. Slots replace a part entirely. The MUI theme, tokens, and sx compose — you never manage colours twice.

5. Dark mode

The grid follows your theme's light/dark mode 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'), so toggling the scheme restyles the header, rows, borders, and toolbar:

Loading demo…
const theme = createTheme({
cssVariables: { colorSchemeSelector: 'class' },
colorSchemes: { light: true, dark: true },
});
// …toggle with useColorScheme().setMode('dark') — the grid follows.

To customise grid colours per scheme, merge createDataTableTheme (palette + optional darkPalette) — it emits colorSchemes overrides that compose cleanly with a cssVariables theme (no flat top-level palette).

6. Right-to-left (RTL)

Set direction: 'rtl' on your theme and the grid mirrors itself — no extra setup. Pinned columns flip side, the resize handle and sort/⋮-menu move to the logical edge, text aligns to the start, and tree indentation and the column separators mirror. The grid sets dir="rtl" on its root, so it works even without a dir attribute on a parent.

Loading demo…
import { ThemeProvider, createTheme } from '@mui/material/styles';

<ThemeProvider theme={(outer) => createTheme(outer, { direction: 'rtl' })}>
<DataTable columns={columns} data={data} enableColumnPinning enableColumnResizing />
</ThemeProvider>