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:
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.
| Token | Defaults from |
|---|---|
--dt-border-color | palette.divider |
--dt-header-bg | palette.grey[50] (light) / palette.grey[900] (dark) |
--dt-header-color | palette.text.secondary |
--dt-row-bg-hover | palette.action.hover |
--dt-row-bg-selected | palette.action.selected |
--dt-row-bg-stripe | subtle tint (used when striped) |
--dt-row-height, --dt-cell-padding-x/y | density preset |
--dt-font-size | density preset |
--dt-radius | theme.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:
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.
import { ThemeProvider, createTheme } from '@mui/material/styles';
<ThemeProvider theme={(outer) => createTheme(outer, { direction: 'rtl' })}>
<DataTable columns={columns} data={data} enableColumnPinning enableColumnResizing />
</ThemeProvider>