-
-
Notifications
You must be signed in to change notification settings - Fork 32.5k
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
[System] Fix nested grid v2 #35994
[System] Fix nested grid v2 #35994
Conversation
@mui/joy: parsed: 0.00% 😍, gzip: +0.10% |
margin: `calc(var(--Grid-rowSpacing) / -2) calc(var(--Grid-columnSpacing) / -2)`, | ||
padding: `calc(var(--Grid-nested2-rowSpacing) / 2) calc(var(--Grid-nested2-columnSpacing) / 2)`, | ||
'--Grid-nested3-rowSpacing': 'var(--Grid-rowSpacing)', | ||
'--Grid-nested3-columnSpacing': 'var(--Grid-columnSpacing)', |
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.
Same suggestion as my comment above
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.
Left a few small question / suggestions, but looks ready for merge!
}), | ||
}), | ||
// variables for the next level grid container | ||
[`--Grid-nested${(ownerState.nested ?? 0) + 1}-rowSpacing`]: 'var(--Grid-rowSpacing)', |
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.
Wouldn't it be simpler to add the nested variables even if the grid is nested? That way we shouldn't need any leveling information.
I mean oversimplification, but something like this should work no?
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.
Not possible because the variables have 2 purposes:
- consumed by the element itself (margin)
- consumed by the next level grid (padding)
If the variables are the same name, they will behave incorrectly:
// Ex. style of the nested grid container level 1
padding: var(--Grid-rowSpacing); // --Grid-rowSpacing is from the root grid
--Grid-nested-rowSpacing: 16px;
margin: calc(var(--Grid-nested-rowSpacing) * -1);
// style of the nested grid container level 2
padding: var(--Grid-nested-rowSpacing); // --Grid-nested-rowSpacing is from the nested grid container level 1
--Grid-nested-rowSpacing: 24px; // ❌ this will cause the padding to behave incorrectly
margin: calc(var(--Grid-nested-rowSpacing) * -1);
This is why the level of information is important to create scope variables for each level.
I am able to simplify the logic by removing nested variables and using only the --Grid-rowSpacing
and --Grid-columnSpacing
, however, the leveling information is still necessary.
If you are not use nested grid container, you will get a simple --Grid-rowSpacing
and --Grid-columnSpacing
as usual.
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.
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.
In order for what I had in mind to work, we would need to bump the specificity, which is not great. This is what I had in mind:
index 148057c105..98201a717b 100644
--- a/packages/mui-system/src/Unstable_Grid/gridGenerator.ts
+++ b/packages/mui-system/src/Unstable_Grid/gridGenerator.ts
@@ -208,6 +208,10 @@ export const generateGridStyles = ({ ownerState }: Props): {} => {
...((ownerState.disableEqualOverflow || ownerState.parentDisableEqualOverflow) && {
padding: `calc(var(--Grid-nested-rowSpacing)) 0px 0px calc(var(--Grid-nested-columnSpacing))`,
}),
+ // for nested grids, set the nested variables to the current rowSpacing and columnSpacing if they are defined
+ '& .MuiGrid2-root': {
+ '--Grid-nested-rowSpacing': 'var(--Grid-rowSpacing, var(--Grid-nested-rowSpacing))',
+ '--Grid-nested-columnSpacing': 'var(--Grid-columnSpacing, var(--Grid-nested-columnSpacing))',
+ }
}
: {
'--Grid-nested-rowSpacing': 'var(--Grid-rowSpacing)',
I will let to you decide what you think it's better. With this one we gain simpler CSS variables, but we are increasing the specificity. I don't expect people to actually change the CSS variable when they have a first class API - prop, so this could be viable solution too.
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.
-
CSS variables does not work if it refers to themselves, so they should be:
+ '& .MuiGrid2-root': { + '--Grid-nested-rowSpacing': 'var(--Grid-rowSpacing)', + '--Grid-nested-columnSpacing': 'var(--Grid-columnSpacing)', + }
-
What you propose would not work if you specify
spacing
prop to the nested grid.
let's say that this is the style of a deeply nested grid (it could be any level), the padding of the nested grid should use the parent spacing variable to behave correctly:
// assume that --Grid-nested-rowSpacing is 8px;
padding: `calc(var(--Grid-nested-rowSpacing) / 2) calc(var(--Grid-nested-columnSpacing) / 2)`
Now if you add the CSS specificity together with spacing prop:
the styles become:
--Grid-nested-rowSpacing: 16px;
--Grid-nested-columnSpacing: 16px;
'& > .MuiGrid2-container': {
'--Grid-nested-rowSpacing': 'var(--Grid-rowSpacing)', // 16px from itself
'--Grid-nested-columnSpacing': 'var(--Grid-columnSpacing)', // 16px from itself
}
// --Grid-nested-rowSpacing resolves to 16px (itself) instead of 8px (parent) ❌ This is wrong.
padding: `calc(var(--Grid-nested-rowSpacing) / 2) calc(var(--Grid-nested-columnSpacing) / 2)`
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.
My latest change fixes the problem and is also better in one aspect. It does not produce nested variables if you don't have nested grids.
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.
CSS variables does not work if it refers to themselves, so they should be:
Ah I didn't know this, I guess for this to work we need some kind of internal variable as described in the answer here: https://stackoverflow.com/questions/59015022/css-variables-defaults-set-if-not-already-set
I understand now what this wouldn't work, thanks for the explanation.
@@ -20,51 +21,52 @@ export default function SpacingGrid() { | |||
`; | |||
|
|||
return ( | |||
<Grid sx={{ flexGrow: 1 }} container spacing={2}> |
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.
This demo does not need to use a nested grid. Simple box is enough.
@@ -161,7 +161,18 @@ export interface GridBaseProps extends Breakpoints { | |||
} | |||
|
|||
export interface GridOwnerState extends GridBaseProps { | |||
nested: boolean; |
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.
Changed to level
sounds better because it is not a boolean anymore, it is a number.
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.
I learnt a lot by reviewing this PR :D
Me too 😄! |
close #35959
After: https://codesandbox.io/s/sleepy-frost-me5qwc?file=/src/App.tsx
Root cause
the nested grid >= level 2 does not behave properly because it uses variables from the top-most grid instead of the closest parent.
Changes
Change the type of the NestedContext to the number and increase it for each level. In each level, create specific variables for the next level.