-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
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
base: master
Are you sure you want to change the base?
Changes from 8 commits
19ae1b7
a8c4527
abd745e
3f3f064
e2e9b02
649ac02
05ca293
870f8f8
84e7251
bdffada
6f211d9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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> | ||
); | ||
} |
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> | ||
); | ||
} |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -116,26 +116,64 @@ | |||||
|
||||||
{{"demo": "StripedGrid.js", "bg": "inline"}} | ||||||
|
||||||
## Theme header and pinned sections | ||||||
## Theme container, header 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: | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. passive –> active voice
Suggested change
|
||||||
|
||||||
```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', | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 Material use |
||||||
}, | ||||||
}, | ||||||
}); | ||||||
``` | ||||||
|
||||||
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 GitHub Actions / runner / vale
|
||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. might be nice to add h3s for |
||||||
|
||||||
```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 GitHub Actions / runner / vale
|
||||||
|
||||||
{{"demo": "BackgroundColorsGrid.js", "bg": "inline", "defaultCodeOpen": false}} | ||||||
|
||||||
## Custom theme | ||||||
|
||||||
The following demo leverages the CSS customization API to match the Ant Design specification. | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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})` | ||
|
@@ -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, | ||
|
||
|
@@ -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', | ||
|
@@ -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', | ||
|
@@ -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, | ||
|
@@ -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}`]: { | ||
|
@@ -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', | ||
|
@@ -670,7 +669,7 @@ export const GridRootStyles = styled('div', { | |
backgroundColor: pinnedSelectedBackgroundColor, | ||
}, | ||
}, | ||
[`& .${c.virtualScrollerContent} .${c.row}`]: { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
[`& .${c.row}`]: { | ||
'&:hover': pinnedHoverStyles, | ||
'&.Mui-selected': pinnedSelectedStyles, | ||
'&.Mui-selected:hover': pinnedSelectedHoverStyles, | ||
|
There was a problem hiding this comment.
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.