diff --git a/docs/data/material/components/grid2/SpacingGrid.js b/docs/data/material/components/grid2/SpacingGrid.js
index 09eb9e9a2d2a07..97d79b33841787 100644
--- a/docs/data/material/components/grid2/SpacingGrid.js
+++ b/docs/data/material/components/grid2/SpacingGrid.js
@@ -1,4 +1,5 @@
import * as React from 'react';
+import Box from '@mui/material/Box';
import Grid from '@mui/material/Unstable_Grid2';
import FormLabel from '@mui/material/FormLabel';
import FormControl from '@mui/material/FormControl';
@@ -20,51 +21,52 @@ export default function SpacingGrid() {
`;
return (
-
-
-
- {[0, 1, 2].map((value) => (
-
-
- theme.palette.mode === 'dark' ? '#1A2027' : '#fff',
- }}
- />
-
- ))}
-
-
-
-
-
-
-
- spacing
-
- {[0, 0.5, 1, 2, 3, 4, 8, 12].map((value) => (
- }
- label={value.toString()}
- />
- ))}
-
-
-
+
+
+ {[0, 1, 2].map((value) => (
+
+
+ theme.palette.mode === 'dark' ? '#1A2027' : '#fff',
+ }}
+ />
-
-
+ ))}
-
+
+
+ spacing
+
+ {[0, 0.5, 1, 2, 3, 4, 8, 12].map((value) => (
+ }
+ label={value.toString()}
+ />
+ ))}
+
+
+
+
+
);
}
diff --git a/docs/data/material/components/grid2/SpacingGrid.tsx b/docs/data/material/components/grid2/SpacingGrid.tsx
index 4505fd4a0727e3..a3fcce0dd0198e 100644
--- a/docs/data/material/components/grid2/SpacingGrid.tsx
+++ b/docs/data/material/components/grid2/SpacingGrid.tsx
@@ -1,4 +1,5 @@
import * as React from 'react';
+import Box from '@mui/material/Box';
import Grid from '@mui/material/Unstable_Grid2';
import FormLabel from '@mui/material/FormLabel';
import FormControl from '@mui/material/FormControl';
@@ -20,51 +21,52 @@ export default function SpacingGrid() {
`;
return (
-
-
-
- {[0, 1, 2].map((value) => (
-
-
- theme.palette.mode === 'dark' ? '#1A2027' : '#fff',
- }}
- />
-
- ))}
-
-
-
-
-
-
-
- spacing
-
- {[0, 0.5, 1, 2, 3, 4, 8, 12].map((value) => (
- }
- label={value.toString()}
- />
- ))}
-
-
-
+
+
+ {[0, 1, 2].map((value) => (
+
+
+ theme.palette.mode === 'dark' ? '#1A2027' : '#fff',
+ }}
+ />
-
-
+ ))}
-
+
+
+ spacing
+
+ {[0, 0.5, 1, 2, 3, 4, 8, 12].map((value) => (
+ }
+ label={value.toString()}
+ />
+ ))}
+
+
+
+
+
);
}
diff --git a/packages/mui-system/src/Unstable_Grid/GridProps.ts b/packages/mui-system/src/Unstable_Grid/GridProps.ts
index f4456f15edafb4..fb87411411531e 100644
--- a/packages/mui-system/src/Unstable_Grid/GridProps.ts
+++ b/packages/mui-system/src/Unstable_Grid/GridProps.ts
@@ -161,7 +161,18 @@ export interface GridBaseProps extends Breakpoints {
}
export interface GridOwnerState extends GridBaseProps {
- nested: boolean;
+ /**
+ * The level of the grid starts from `0`
+ * and increases when the grid nests inside another grid regardless of container or item.
+ *
+ * ```js
+ * // level 0
+ * // level 1
+ * // level 2
+ * // level 1
+ * ```
+ */
+ level: number;
gridSize: Partial>;
gridOffset: Partial>;
}
diff --git a/packages/mui-system/src/Unstable_Grid/createGrid.tsx b/packages/mui-system/src/Unstable_Grid/createGrid.tsx
index 6dc66f30b49234..920caf5073731a 100644
--- a/packages/mui-system/src/Unstable_Grid/createGrid.tsx
+++ b/packages/mui-system/src/Unstable_Grid/createGrid.tsx
@@ -58,7 +58,7 @@ export default function createGrid(
componentName = 'MuiGrid',
} = options;
- const NestedContext = React.createContext(false);
+ const NestedContext = React.createContext(0);
const OverflowContext = React.createContext(undefined);
const useUtilityClasses = (ownerState: GridOwnerState, theme: typeof defaultTheme) => {
@@ -93,7 +93,7 @@ export default function createGrid(
const theme = useTheme();
const themeProps = useThemeProps(inProps);
const props = extendSxProp(themeProps) as Omit; // `color` type conflicts with html color attribute.
- const nested = React.useContext(NestedContext);
+ const level = React.useContext(NestedContext);
const overflow = React.useContext(OverflowContext);
const {
className,
@@ -110,7 +110,7 @@ export default function createGrid(
} = props;
// Because `disableEqualOverflow` can be set from the theme's defaultProps, the **nested** grid should look at the instance props instead.
let disableEqualOverflow = themeDisableEqualOverflow;
- if (nested && themeDisableEqualOverflow !== undefined) {
+ if (level && themeDisableEqualOverflow !== undefined) {
disableEqualOverflow = inProps.disableEqualOverflow;
}
// collect breakpoints related props because they can be customized from the theme.
@@ -128,15 +128,15 @@ export default function createGrid(
}
});
- const columns = inProps.columns ?? (nested ? undefined : columnsProp);
- const spacing = inProps.spacing ?? (nested ? undefined : spacingProp);
+ const columns = inProps.columns ?? (level ? undefined : columnsProp);
+ const spacing = inProps.spacing ?? (level ? undefined : spacingProp);
const rowSpacing =
- inProps.rowSpacing ?? inProps.spacing ?? (nested ? undefined : rowSpacingProp);
+ inProps.rowSpacing ?? inProps.spacing ?? (level ? undefined : rowSpacingProp);
const columnSpacing =
- inProps.columnSpacing ?? inProps.spacing ?? (nested ? undefined : columnSpacingProp);
+ inProps.columnSpacing ?? inProps.spacing ?? (level ? undefined : columnSpacingProp);
const ownerState = {
...props,
- nested,
+ level,
columns,
container,
direction,
@@ -162,8 +162,8 @@ export default function createGrid(
/>
);
- if (!nested) {
- result = {result};
+ if (container) {
+ result = {result};
}
if (disableEqualOverflow !== undefined && disableEqualOverflow !== (overflow ?? false)) {
diff --git a/packages/mui-system/src/Unstable_Grid/gridGenerator.test.js b/packages/mui-system/src/Unstable_Grid/gridGenerator.test.js
index 21dfe67b5ed89c..0cca34f51f1477 100644
--- a/packages/mui-system/src/Unstable_Grid/gridGenerator.test.js
+++ b/packages/mui-system/src/Unstable_Grid/gridGenerator.test.js
@@ -239,33 +239,39 @@ describe('grid generator', () => {
describe('generateGridStyles', () => {
it('root container', () => {
- const result = generateGridStyles({ ownerState: { container: true, nested: false } });
+ const result = generateGridStyles({ ownerState: { container: true, level: 0 } });
expect(result).to.deep.equal({
minWidth: 0,
boxSizing: 'border-box',
display: 'flex',
flexWrap: 'wrap',
margin: 'calc(var(--Grid-rowSpacing) / -2) calc(var(--Grid-columnSpacing) / -2)',
- '--Grid-nested-rowSpacing': 'var(--Grid-rowSpacing)',
- '--Grid-nested-columnSpacing': 'var(--Grid-columnSpacing)',
});
});
- it('nested container', () => {
- const result = generateGridStyles({ ownerState: { container: true, nested: true } });
+ it('nested container level 1', () => {
+ const result = generateGridStyles({ ownerState: { container: true, level: 1 } });
sinon.assert.match(result, {
- margin: `calc(var(--Grid-rowSpacing) / -2) calc(var(--Grid-columnSpacing) / -2)`,
- padding: `calc(var(--Grid-nested-rowSpacing) / 2) calc(var(--Grid-nested-columnSpacing) / 2)`,
+ margin: `calc(var(--Grid-rowSpacing1) / -2) calc(var(--Grid-columnSpacing1) / -2)`,
+ padding: `calc(var(--Grid-rowSpacing) / 2) calc(var(--Grid-columnSpacing) / 2)`,
+ });
+ });
+
+ it('nested container level 2', () => {
+ const result = generateGridStyles({ ownerState: { container: true, level: 2 } });
+ sinon.assert.match(result, {
+ margin: `calc(var(--Grid-rowSpacing2) / -2) calc(var(--Grid-columnSpacing2) / -2)`,
+ padding: `calc(var(--Grid-rowSpacing1) / 2) calc(var(--Grid-columnSpacing1) / 2)`,
});
});
it('root container with disableEqualOverflow', () => {
const result = generateGridStyles({
- ownerState: { container: true, nested: true, disableEqualOverflow: true },
+ ownerState: { container: true, level: 1, disableEqualOverflow: true },
});
sinon.assert.match(result, {
- margin: `calc(var(--Grid-rowSpacing) * -1) 0px 0px calc(var(--Grid-columnSpacing) * -1)`,
- padding: `calc(var(--Grid-nested-rowSpacing)) 0px 0px calc(var(--Grid-nested-columnSpacing))`,
+ margin: `calc(var(--Grid-rowSpacing1) * -1) 0px 0px calc(var(--Grid-columnSpacing1) * -1)`,
+ padding: `var(--Grid-rowSpacing) 0px 0px var(--Grid-columnSpacing)`,
});
});
@@ -273,19 +279,19 @@ describe('grid generator', () => {
const result = generateGridStyles({
ownerState: {
container: true,
- nested: true,
+ level: 1,
disableEqualOverflow: false,
parentDisableEqualOverflow: true,
},
});
sinon.assert.match(result, {
- margin: `calc(var(--Grid-rowSpacing) / -2) calc(var(--Grid-columnSpacing) / -2)`,
- padding: `calc(var(--Grid-nested-rowSpacing)) 0px 0px calc(var(--Grid-nested-columnSpacing))`,
+ margin: `calc(var(--Grid-rowSpacing1) / -2) calc(var(--Grid-columnSpacing1) / -2)`,
+ padding: `var(--Grid-rowSpacing) 0px 0px var(--Grid-columnSpacing)`,
});
});
it('item', () => {
- const result = generateGridStyles({ ownerState: { container: false, nested: false } });
+ const result = generateGridStyles({ ownerState: { container: false, level: 1 } });
expect(result).to.deep.equal({
minWidth: 0,
boxSizing: 'border-box',
@@ -298,7 +304,16 @@ describe('grid generator', () => {
ownerState: { container: false, disableEqualOverflow: true },
});
sinon.assert.match(result, {
- padding: `calc(var(--Grid-rowSpacing)) 0px 0px calc(var(--Grid-columnSpacing))`,
+ padding: `var(--Grid-rowSpacing) 0px 0px var(--Grid-columnSpacing)`,
+ });
+ });
+
+ it('item level 2', () => {
+ const result = generateGridStyles({
+ ownerState: { container: false, disableEqualOverflow: true, level: 2 },
+ });
+ sinon.assert.match(result, {
+ padding: `var(--Grid-rowSpacing1) 0px 0px var(--Grid-columnSpacing1)`,
});
});
});
@@ -454,6 +469,14 @@ describe('grid generator', () => {
},
});
});
+
+ it('nested item level 1 should have default spacing set to parent', () => {
+ const result = generateGridRowSpacingStyles({
+ theme: { breakpoints },
+ ownerState: { container: true, level: 1 },
+ });
+ expect(result['--Grid-rowSpacing1']).to.equal('var(--Grid-rowSpacing)');
+ });
});
describe('generateGridColumnSpacingStyles', () => {
@@ -510,6 +533,14 @@ describe('grid generator', () => {
},
});
});
+
+ it('nested item level 1 should have default spacing set to parent', () => {
+ const result = generateGridColumnSpacingStyles({
+ theme: { breakpoints },
+ ownerState: { container: true, level: 1 },
+ });
+ expect(result['--Grid-columnSpacing1']).to.equal('var(--Grid-columnSpacing)');
+ });
});
describe('generateGridOffsetStyles', () => {
diff --git a/packages/mui-system/src/Unstable_Grid/gridGenerator.ts b/packages/mui-system/src/Unstable_Grid/gridGenerator.ts
index 148057c105a734..34cc5e846dc128 100644
--- a/packages/mui-system/src/Unstable_Grid/gridGenerator.ts
+++ b/packages/mui-system/src/Unstable_Grid/gridGenerator.ts
@@ -12,6 +12,25 @@ interface Iterator {
(appendStyle: (responsiveStyles: Record, style: object) => void, value: T): void;
}
+function isNestedContainer(ownerState: Props['ownerState']) {
+ return ownerState.level > 0 && ownerState.container;
+}
+
+function createGetSelfSpacing(ownerState: Props['ownerState']) {
+ return function getSelfSpacing(axis: 'row' | 'column') {
+ return `var(--Grid-${axis}Spacing${ownerState.level || ''})`;
+ };
+}
+
+function createGetParentSpacing(ownerState: Props['ownerState']) {
+ return function getParentSpacing(axis: 'row' | 'column') {
+ if (ownerState.level === 0) {
+ return `var(--Grid-${axis}Spacing)`;
+ }
+ return `var(--Grid-${axis}Spacing${ownerState.level - 1 || ''})`;
+ };
+}
+
export const filterBreakpointKeys = (breakpointsKeys: Breakpoint[], responsiveKeys: string[]) =>
breakpointsKeys.filter((key: string) => responsiveKeys.includes(key));
@@ -66,6 +85,7 @@ export const traverseBreakpoints = (
};
export const generateGridSizeStyles = ({ theme, ownerState }: Props) => {
+ const getSelfSpacing = createGetSelfSpacing(ownerState);
const styles = {};
traverseBreakpoints<'auto' | number | true>(
theme.breakpoints,
@@ -93,7 +113,7 @@ export const generateGridSizeStyles = ({ theme, ownerState }: Props) => {
flexGrow: 0,
flexBasis: 'auto',
width: `calc(100% * ${value} / var(--Grid-columns)${
- ownerState.nested && ownerState.container ? ` + var(--Grid-columnSpacing)` : ''
+ isNestedContainer(ownerState) ? ` + ${getSelfSpacing('column')}` : ''
})`,
};
}
@@ -141,13 +161,21 @@ export const generateGridRowSpacingStyles = ({ theme, ownerState }: Props) => {
if (!ownerState.container) {
return {};
}
- const styles = {};
+ const getParentSpacing = createGetParentSpacing(ownerState);
+ const styles = isNestedContainer(ownerState)
+ ? {
+ // Set the default spacing as its parent spacing.
+ // It will be overridden if spacing props are provided
+ [`--Grid-rowSpacing${ownerState.level || ''}`]: getParentSpacing('row'),
+ }
+ : {};
traverseBreakpoints(
theme.breakpoints,
ownerState.rowSpacing,
(appendStyle, value) => {
appendStyle(styles, {
- '--Grid-rowSpacing': typeof value === 'string' ? value : theme.spacing?.(value),
+ [`--Grid-rowSpacing${ownerState.level || ''}`]:
+ typeof value === 'string' ? value : theme.spacing?.(value),
});
},
);
@@ -158,13 +186,21 @@ export const generateGridColumnSpacingStyles = ({ theme, ownerState }: Props) =>
if (!ownerState.container) {
return {};
}
- const styles = {};
+ const getParentSpacing = createGetParentSpacing(ownerState);
+ const styles = isNestedContainer(ownerState)
+ ? {
+ // Set the default spacing as its parent spacing.
+ // It will be overridden if spacing props are provided
+ [`--Grid-columnSpacing${ownerState.level || ''}`]: getParentSpacing('column'),
+ }
+ : {};
traverseBreakpoints(
theme.breakpoints,
ownerState.columnSpacing,
(appendStyle, value) => {
appendStyle(styles, {
- '--Grid-columnSpacing': typeof value === 'string' ? value : theme.spacing?.(value),
+ [`--Grid-columnSpacing${ownerState.level || ''}`]:
+ typeof value === 'string' ? value : theme.spacing?.(value),
});
},
);
@@ -187,39 +223,31 @@ export const generateGridDirectionStyles = ({ theme, ownerState }: Props) => {
};
export const generateGridStyles = ({ ownerState }: Props): {} => {
+ const getSelfSpacing = createGetSelfSpacing(ownerState);
+ const getParentSpacing = createGetParentSpacing(ownerState);
return {
minWidth: 0,
boxSizing: 'border-box',
- ...(ownerState.container
- ? {
- display: 'flex',
- flexWrap: 'wrap',
- ...(ownerState.wrap &&
- ownerState.wrap !== 'wrap' && {
- flexWrap: ownerState.wrap,
- }),
- margin: `calc(var(--Grid-rowSpacing) / -2) calc(var(--Grid-columnSpacing) / -2)`,
- ...(ownerState.disableEqualOverflow && {
- margin: `calc(var(--Grid-rowSpacing) * -1) 0px 0px calc(var(--Grid-columnSpacing) * -1)`,
- }),
- ...(ownerState.nested
- ? {
- padding: `calc(var(--Grid-nested-rowSpacing) / 2) calc(var(--Grid-nested-columnSpacing) / 2)`,
- ...((ownerState.disableEqualOverflow || ownerState.parentDisableEqualOverflow) && {
- padding: `calc(var(--Grid-nested-rowSpacing)) 0px 0px calc(var(--Grid-nested-columnSpacing))`,
- }),
- }
- : {
- '--Grid-nested-rowSpacing': 'var(--Grid-rowSpacing)',
- '--Grid-nested-columnSpacing': 'var(--Grid-columnSpacing)',
- }),
- }
- : {
- padding: `calc(var(--Grid-rowSpacing) / 2) calc(var(--Grid-columnSpacing) / 2)`,
- ...(ownerState.disableEqualOverflow && {
- padding: `calc(var(--Grid-rowSpacing)) 0px 0px calc(var(--Grid-columnSpacing))`,
- }),
+ ...(ownerState.container && {
+ display: 'flex',
+ flexWrap: 'wrap',
+ ...(ownerState.wrap &&
+ ownerState.wrap !== 'wrap' && {
+ flexWrap: ownerState.wrap,
}),
+ margin: `calc(${getSelfSpacing('row')} / -2) calc(${getSelfSpacing('column')} / -2)`,
+ ...(ownerState.disableEqualOverflow && {
+ margin: `calc(${getSelfSpacing('row')} * -1) 0px 0px calc(${getSelfSpacing(
+ 'column',
+ )} * -1)`,
+ }),
+ }),
+ ...((!ownerState.container || isNestedContainer(ownerState)) && {
+ padding: `calc(${getParentSpacing('row')} / 2) calc(${getParentSpacing('column')} / 2)`,
+ ...((ownerState.disableEqualOverflow || ownerState.parentDisableEqualOverflow) && {
+ padding: `${getParentSpacing('row')} 0px 0px ${getParentSpacing('column')}`,
+ }),
+ }),
};
};