Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[DataGrid] Add default background color to grid #16066

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions docs/data/data-grid/style/BackgroundColorsGrid.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import * as React from 'react';
import { ThemeProvider, createTheme } from '@mui/material/styles';

import { DataGridPremium } from '@mui/x-data-grid-premium';
import Stack from '@mui/material/Stack';
import ToggleButtonGroup from '@mui/material/ToggleButtonGroup';
import ToggleButton from '@mui/material/ToggleButton';
import DarkModeIcon from '@mui/icons-material/DarkMode';
import LightModeIcon from '@mui/icons-material/LightMode';

const getTheme = (mode) =>
createTheme({
palette: {
mode,
DataGrid: {
bg: mode === 'light' ? '#f8fafc' : '#334155',
pinnedBg: mode === 'light' ? '#f1f5f9' : '#293548',
headerBg: mode === 'light' ? '#eaeff5' : '#1e293b',
},
},
});

const columns = [
{ field: 'id', headerName: 'ID', width: 90 },
{
field: 'firstName',
headerName: 'First name',
width: 150,
editable: true,
},
{
field: 'lastName',
headerName: 'Last name',
width: 150,
editable: true,
},
{
field: 'age',
headerName: 'Age',
type: 'number',
width: 110,
editable: true,
},
{
field: 'fullName',
headerName: 'Full name',
description: 'This column has a value getter and is not sortable.',
sortable: false,
width: 160,
valueGetter: (value, row) => `${row.firstName || ''} ${row.lastName || ''}`,
},
];

const rows = [
{ id: 1, lastName: 'Snow', firstName: 'Jon', age: 14 },
{ id: 2, lastName: 'Lannister', firstName: 'Cersei', age: 31 },
{ id: 3, lastName: 'Lannister', firstName: 'Jaime', age: 31 },
{ id: 4, lastName: 'Stark', firstName: 'Arya', age: 11 },
{ id: 5, lastName: 'Targaryen', firstName: 'Daenerys', age: null },
{ id: 6, lastName: 'Melisandre', firstName: null, age: 150 },
{ id: 7, lastName: 'Clifford', firstName: 'Ferrara', age: 44 },
{ id: 8, lastName: 'Frances', firstName: 'Rossini', age: 36 },
{ id: 9, lastName: 'Roxie', firstName: 'Harvey', age: 65 },
];

export default function BackgroundColorsGrid() {
const [mode, setMode] = React.useState('light');
const theme = React.useMemo(() => getTheme(mode), [mode]);

return (
<Stack direction="column" gap={1} style={{ width: '100%', height: 400 }}>
<ToggleButtonGroup
size="small"
color="primary"
value={mode}
onChange={(event, value) => setMode(value === null ? mode : value)}
exclusive
>
<ToggleButton value="light" aria-label="Light mode" sx={{ gap: 1 }}>
<LightModeIcon fontSize="small" /> Light
</ToggleButton>
<ToggleButton value="dark" aria-label="Dark mode" sx={{ gap: 1 }}>
<DarkModeIcon fontSize="small" /> Dark
</ToggleButton>
</ToggleButtonGroup>

<ThemeProvider theme={theme}>
<DataGridPremium
rows={rows}
columns={columns}
initialState={{
pagination: {
paginationModel: {
pageSize: 5,
},
},
pinnedColumns: {
left: ['id'],
},
}}
pinnedRows={{
bottom: [rows[0]],
}}
/>
</ThemeProvider>
</Stack>
);
}
110 changes: 110 additions & 0 deletions docs/data/data-grid/style/BackgroundColorsGrid.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
import * as React from 'react';
import { ThemeProvider, createTheme } from '@mui/material/styles';
import { GridColDef } from '@mui/x-data-grid';
import { DataGridPremium } from '@mui/x-data-grid-premium';
import Stack from '@mui/material/Stack';
import ToggleButtonGroup from '@mui/material/ToggleButtonGroup';
import ToggleButton from '@mui/material/ToggleButton';
import DarkModeIcon from '@mui/icons-material/DarkMode';
import LightModeIcon from '@mui/icons-material/LightMode';

type PaletteMode = 'light' | 'dark';

const getTheme = (mode: PaletteMode) =>
createTheme({
palette: {
mode,
DataGrid: {
bg: mode === 'light' ? '#f8fafc' : '#334155',
pinnedBg: mode === 'light' ? '#f1f5f9' : '#293548',
headerBg: mode === 'light' ? '#eaeff5' : '#1e293b',
},
},
});

const columns: GridColDef<(typeof rows)[number]>[] = [
{ field: 'id', headerName: 'ID', width: 90 },
{
field: 'firstName',
headerName: 'First name',
width: 150,
editable: true,
},
{
field: 'lastName',
headerName: 'Last name',
width: 150,
editable: true,
},
{
field: 'age',
headerName: 'Age',
type: 'number',
width: 110,
editable: true,
},
{
field: 'fullName',
headerName: 'Full name',
description: 'This column has a value getter and is not sortable.',
sortable: false,
width: 160,
valueGetter: (value, row) => `${row.firstName || ''} ${row.lastName || ''}`,
},
];

const rows = [
{ id: 1, lastName: 'Snow', firstName: 'Jon', age: 14 },
{ id: 2, lastName: 'Lannister', firstName: 'Cersei', age: 31 },
{ id: 3, lastName: 'Lannister', firstName: 'Jaime', age: 31 },
{ id: 4, lastName: 'Stark', firstName: 'Arya', age: 11 },
{ id: 5, lastName: 'Targaryen', firstName: 'Daenerys', age: null },
{ id: 6, lastName: 'Melisandre', firstName: null, age: 150 },
{ id: 7, lastName: 'Clifford', firstName: 'Ferrara', age: 44 },
{ id: 8, lastName: 'Frances', firstName: 'Rossini', age: 36 },
{ id: 9, lastName: 'Roxie', firstName: 'Harvey', age: 65 },
];

export default function BackgroundColorsGrid() {
const [mode, setMode] = React.useState<PaletteMode>('light');
const theme = React.useMemo(() => getTheme(mode), [mode]);

return (
<Stack direction="column" gap={1} style={{ width: '100%', height: 400 }}>
<ToggleButtonGroup
size="small"
color="primary"
value={mode}
onChange={(event, value) => setMode(value === null ? mode : value)}
exclusive
>
<ToggleButton value="light" aria-label="Light mode" sx={{ gap: 1 }}>
<LightModeIcon fontSize="small" /> Light
</ToggleButton>
<ToggleButton value="dark" aria-label="Dark mode" sx={{ gap: 1 }}>
<DarkModeIcon fontSize="small" /> Dark
</ToggleButton>
</ToggleButtonGroup>

<ThemeProvider theme={theme}>
<DataGridPremium
rows={rows}
columns={columns}
initialState={{
pagination: {
paginationModel: {
pageSize: 5,
},
},
pinnedColumns: {
left: ['id'],
},
}}
pinnedRows={{
bottom: [rows[0]],
}}
/>
</ThemeProvider>
</Stack>
);
}
54 changes: 46 additions & 8 deletions docs/data/data-grid/style/style.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,26 +116,64 @@

{{"demo": "StripedGrid.js", "bg": "inline"}}

## Theme header and pinned sections
## Theme container, header and pinned sections
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oxford comma. 😁 and is "Theme" necessary here? If not I think it's better without, for the sake of keeping the header as short as possible. I'm on the fence about whether or not to pluralize everything so I'll leave that to your judgement.

Suggested change
## Theme container, header and pinned sections
## Containers, headers, and pinned sections


By default, the Data Grid uses the Material UI `theme.palette.background.default` color for the background of its header and pinned sections. These elements require a solid color to hide the scrollable content behind them. You can override that color with the following configuration:
By default, the Data Grid uses the Material UI `theme.palette.background.default` color for the background color of the grid container, the column headers, and the pinned rows and columns.

The various background colors can be overridden with the following configuration:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

passive –> active voice

Suggested change
The various background colors can be overridden with the following configuration:
You can override these background colors with the following theme configuration:


```tsx
import { createTheme } from '@mui/material/styles';
import type {} from '@mui/x-data-grid/themeAugmentation';

const theme = createTheme({
mixins: {
MuiDataGrid: {
// Pinned columns sections
pinnedBackground: '#340606',
// Headers, and top & bottom fixed rows
containerBackground: '#343434',
palette: {
DataGrid: {
// Container background
bg: '#f8fafc',
// Pinned rows and columns background
pinnedBg: '#f1f5f9',
// Column header background
headerBg: '#eaeff5',
Copy link
Member Author

@KenanYusuf KenanYusuf Jan 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is another breaking change to make Data Grid theming consistent with Material UI.

Instead of using the mixins theme property, we add DataGrid to the palette—in addition to being consistent with other component color options, this gives us built-in support for light/dark mode theming with colorSchemes (as shown in the snippet below this).

Material use bg instead of background, so also updated the property names for consistency.

},
},
});
```

Material UI v6 users can use the `colorSchemes` property to specify different colors for light and dark mode:

Check failure on line 143 in docs/data/data-grid/style/style.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [MUI.MuiBrandName] Use a non-breaking space (option+space on Mac, Alt+0160 on Windows or AltGr+Space on Linux, instead of space) for brand name ('Material UI' instead of 'Material UI') Raw Output: {"message": "[MUI.MuiBrandName] Use a non-breaking space (option+space on Mac, Alt+0160 on Windows or AltGr+Space on Linux, instead of space) for brand name ('Material UI' instead of 'Material UI')", "location": {"path": "docs/data/data-grid/style/style.md", "range": {"start": {"line": 143, "column": 1}}}, "severity": "ERROR"}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

might be nice to add h3s for ### Material UI v6 and ### Material UI v5 so users can quickly differentiate between the two samples when skimming


```tsx
import { createTheme } from '@mui/material/styles';
import type {} from '@mui/x-data-grid/themeAugmentation';

const theme = createTheme({
colorSchemes: {
light: {
palette: {
DataGrid: {
bg: '#f8fafc',
pinnedBg: '#f1f5f9',
headerBg: '#eaeff5',
},
},
},
dark: {
palette: {
DataGrid: {
bg: '#334155',
pinnedBg: '#293548',
headerBg: '#1e293b',
},
},
},
},
});
```

Material UI v5 supports specifying different colors for light and dark mode with two different themes, as shown in the demo below.

Check failure on line 173 in docs/data/data-grid/style/style.md

View workflow job for this annotation

GitHub Actions / runner / vale

[vale] reported by reviewdog 🐶 [MUI.MuiBrandName] Use a non-breaking space (option+space on Mac, Alt+0160 on Windows or AltGr+Space on Linux, instead of space) for brand name ('Material UI' instead of 'Material UI') Raw Output: {"message": "[MUI.MuiBrandName] Use a non-breaking space (option+space on Mac, Alt+0160 on Windows or AltGr+Space on Linux, instead of space) for brand name ('Material UI' instead of 'Material UI')", "location": {"path": "docs/data/data-grid/style/style.md", "range": {"start": {"line": 173, "column": 1}}}, "severity": "ERROR"}

{{"demo": "BackgroundColorsGrid.js", "bg": "inline", "defaultCodeOpen": false}}

## Custom theme

The following demo leverages the CSS customization API to match the Ant Design specification.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useGridColumnHeaders } from '../hooks/features/columnHeaders/useGridCol

const Filler = styled('div')({
flex: 1,
backgroundColor: 'var(--DataGrid-containerBackground)',
backgroundColor: 'var(--DataGrid-headerBackground)',
});

export interface GridColumnHeadersProps
Expand Down
25 changes: 12 additions & 13 deletions packages/x-data-grid/src/components/containers/GridRootStyles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,11 +146,9 @@ export const GridRootStyles = styled('div', {
const borderColor = getBorderColor(t);
const radius = t.shape.borderRadius;

const containerBackground = t.vars
? t.vars.palette.background.default
: (t.mixins.MuiDataGrid?.containerBackground ?? t.palette.background.default);

const pinnedBackground = t.mixins.MuiDataGrid?.pinnedBackground ?? containerBackground;
const background = (t.vars || t).palette.DataGrid?.bg ?? (t.vars || t).palette.background.default;
const headerBackground = (t.vars || t).palette.DataGrid?.headerBg ?? background;
const pinnedBackground = (t.vars || t).palette.DataGrid?.pinnedBg ?? background;

const overlayBackground = t.vars
? `rgba(${t.vars.palette.background.defaultChannel} / ${t.vars.palette.action.disabledOpacity})`
Expand Down Expand Up @@ -218,7 +216,8 @@ export const GridRootStyles = styled('div', {
'--unstable_DataGrid-headWeight': t.typography.fontWeightMedium,
'--unstable_DataGrid-overlayBackground': overlayBackground,

'--DataGrid-containerBackground': containerBackground,
'--DataGrid-background': background,
'--DataGrid-headerBackground': headerBackground,
'--DataGrid-pinnedBackground': pinnedBackground,
'--DataGrid-rowBorderColor': borderColor,

Expand All @@ -243,6 +242,7 @@ export const GridRootStyles = styled('div', {
borderStyle: 'solid',
borderColor,
borderRadius: 'var(--unstable_DataGrid-radius)',
backgroundColor: 'var(--DataGrid-background)',
color: (t.vars || t).palette.text.primary,
...t.typography.body2,
outline: 'none',
Expand Down Expand Up @@ -414,7 +414,7 @@ export const GridRootStyles = styled('div', {
[`& .${c['columnHeader--pinnedLeft']}, & .${c['columnHeader--pinnedRight']}`]: {
position: 'sticky',
zIndex: 4, // Should be above the column separator
background: 'var(--DataGrid-pinnedBackground)',
background: 'var(--DataGrid-headerBackground)',
},
[`& .${c.columnSeparator}`]: {
position: 'absolute',
Expand All @@ -429,6 +429,7 @@ export const GridRootStyles = styled('div', {
},
[`& .${c.columnHeaders}`]: {
width: 'var(--DataGrid-rowWidth)',
backgroundColor: 'var(--DataGrid-headerBackground)',
},
'@media (hover: hover)': {
[`& .${c.columnHeader}:hover`]: columnHeaderStyles,
Expand Down Expand Up @@ -537,11 +538,6 @@ export const GridRootStyles = styled('div', {
},
'&.Mui-selected': selectedStyles,
},
[`& .${c['container--top']}, & .${c['container--bottom']}`]: {
'[role=row]': {
background: 'var(--DataGrid-containerBackground)',
},
},

/* Cell styles */
[`& .${c.cell}`]: {
Expand All @@ -561,6 +557,9 @@ export const GridRootStyles = styled('div', {
[`& .${c['virtualScrollerContent--overflowed']} .${c['row--lastVisible']} .${c.cell}`]: {
borderTopColor: 'transparent',
},
[`& .${c.pinnedRows}`]: {
backgroundColor: 'var(--DataGrid-pinnedBackground)',
},
[`& .${c['pinnedRows--top']} :first-of-type`]: {
[`& .${c.cell}, .${c.scrollbarFiller}`]: {
borderTop: 'none',
Expand Down Expand Up @@ -670,7 +669,7 @@ export const GridRootStyles = styled('div', {
backgroundColor: pinnedSelectedBackgroundColor,
},
},
[`& .${c.virtualScrollerContent} .${c.row}`]: {
Copy link
Member Author

@KenanYusuf KenanYusuf Jan 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ensures that pinned column cells in pinned rows get hover styles too.

Before - Hovering pinned row

Screenshot 2025-01-03 at 11 56 50

After - Hovering pinned row

Screenshot 2025-01-03 at 11 57 01

[`& .${c.row}`]: {
'&:hover': pinnedHoverStyles,
'&.Mui-selected': pinnedSelectedStyles,
'&.Mui-selected:hover': pinnedSelectedHoverStyles,
Expand Down
Loading
Loading