From 638620be3e1a79173605b2e65ceeb24ca3c8e121 Mon Sep 17 00:00:00 2001 From: siriwatknp Date: Tue, 12 Jul 2022 15:19:51 +0700 Subject: [PATCH 1/5] Revert "Remove disable overflow equal feature" This reverts commit 906db8e0885815cb365f0dce3dfaf9fada2dafe1. --- .../system/components/grid/OverflowGrid.js | 54 +++++++++++++++ docs/data/system/components/grid/grid.md | 14 ++++ docs/pages/system/api/grid.json | 1 + docs/translations/api-docs/grid/grid.json | 1 + .../mui-system/src/Unstable_Grid/Grid.test.js | 65 +++++++++++++++++++ .../mui-system/src/Unstable_Grid/Grid.tsx | 4 ++ .../mui-system/src/Unstable_Grid/GridProps.ts | 4 ++ .../src/Unstable_Grid/createGrid.tsx | 19 ++++++ .../src/Unstable_Grid/gridGenerator.test.js | 43 ++++++++++++ .../src/Unstable_Grid/gridGenerator.ts | 9 +++ 10 files changed, 214 insertions(+) create mode 100644 docs/data/system/components/grid/OverflowGrid.js diff --git a/docs/data/system/components/grid/OverflowGrid.js b/docs/data/system/components/grid/OverflowGrid.js new file mode 100644 index 00000000000000..6d2738ea649cc9 --- /dev/null +++ b/docs/data/system/components/grid/OverflowGrid.js @@ -0,0 +1,54 @@ +import * as React from 'react'; +import Box from '@mui/system/Box'; +import Grid from '@mui/system/Grid'; +import styled from '@mui/system/styled'; + +const Item = styled('div')(({ theme }) => ({ + backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff', + border: '1px solid', + borderColor: theme.palette.mode === 'dark' ? '#444d58' : '#ced7e0', + padding: theme.spacing(1), + borderRadius: '4px', + textAlign: 'center', +})); + +export default function AutoGrid() { + return ( + ({ + display: 'flex', + flexDirection: 'column', + gap: 3, + '& > div': { + overflow: 'auto hidden', + '&::-webkit-scrollbar': { height: 10, WebkitAppearance: 'none' }, + '&::-webkit-scrollbar-thumb': { + borderRadius: 8, + border: '2px solid', + borderColor: theme.palette.mode === 'dark' ? '' : '#E7EBF0', + backgroundColor: 'rgba(0 0 0 / 0.5)', + }, + }, + })} + > + + + + Scroll bar appears + + + + + + + `disableEqualOverflow` prevents scrollbar + + + + + ); +} diff --git a/docs/data/system/components/grid/grid.md b/docs/data/system/components/grid/grid.md index 0e28986debcae5..dedc5828d3b53e 100644 --- a/docs/data/system/components/grid/grid.md +++ b/docs/data/system/components/grid/grid.md @@ -156,6 +156,20 @@ declare module '@mui/system' { } ``` +::: + +## Prevent scrollbar + +If you use grid as a container in a small viewport, you might see a horizontal scrollbar because the negative margin is applied on all sides of the grid container. + +To prevent the scrollbar, set `disableEqualOverflow` prop to `true`. It will enable negative margin only on the top and left sides of the grid which remove overflow on the right-hand side. + +{{"demo": "OverflowGrid.js", "bg": true}} + +:::warning +You should avoid adding borders or background to the grid when `disableEqualOverflow: true` because the negative margin (applied only at the top and left sides) makes the grid visually misaligned. +::: + ## Limitations ### direction column and column-reverse diff --git a/docs/pages/system/api/grid.json b/docs/pages/system/api/grid.json index f57038887ffade..566f0fa04968bf 100644 --- a/docs/pages/system/api/grid.json +++ b/docs/pages/system/api/grid.json @@ -20,6 +20,7 @@ "description": "'column-reverse'
| 'column'
| 'row-reverse'
| 'row'
| Array<'column-reverse'
| 'column'
| 'row-reverse'
| 'row'>
| object" } }, + "disableEqualOverflow": { "type": { "name": "bool" } }, "lg": { "type": { "name": "union", "description": "'auto'
| number
| bool" } }, diff --git a/docs/translations/api-docs/grid/grid.json b/docs/translations/api-docs/grid/grid.json index 0698e6942801b8..5f47be155550d5 100644 --- a/docs/translations/api-docs/grid/grid.json +++ b/docs/translations/api-docs/grid/grid.json @@ -6,6 +6,7 @@ "columnSpacing": "Defines the horizontal space between the type item components. It overrides the value of the spacing prop.", "container": "If true, the component will have the flex container behavior. You should be wrapping items with a container.", "direction": "Defines the flex-direction style property. It is applied for all screen sizes.", + "disableEqualOverflow": "If true, the negative margin and padding are apply only to the top and left sides of the grid.", "lg": "If a number, it sets the number of columns the grid item uses. It can't be greater than the total number of columns of the container (12 by default). If 'auto', the grid item's width matches its content. If false, the prop is ignored. If true, the grid item's width grows to use the space available in the grid container. The value is applied for the lg breakpoint and wider screens if not overridden.", "lgOffset": "If a number, it sets the margin-left equals to the number of columns the grid item uses. If 'auto', the grid item push itself to the right-end of the container. The value is applied for the lg breakpoint and wider screens if not overridden.", "md": "If a number, it sets the number of columns the grid item uses. It can't be greater than the total number of columns of the container (12 by default). If 'auto', the grid item's width matches its content. If false, the prop is ignored. If true, the grid item's width grows to use the space available in the grid container. The value is applied for the md breakpoint and wider screens if not overridden.", diff --git a/packages/mui-system/src/Unstable_Grid/Grid.test.js b/packages/mui-system/src/Unstable_Grid/Grid.test.js index 5299976d42680f..b9f706a530362b 100644 --- a/packages/mui-system/src/Unstable_Grid/Grid.test.js +++ b/packages/mui-system/src/Unstable_Grid/Grid.test.js @@ -211,6 +211,71 @@ describe('System ', () => { }); }); + describe('prop: disableEqualOverflow', () => { + it('should apply to top and left sides only', function test() { + if (/jsdom/.test(window.navigator.userAgent)) { + this.skip(); + } + const { container } = render( + + + , + ); + + expect(container.firstChild).toHaveComputedStyle({ + marginTop: '-16px', + marginLeft: '-16px', + }); + expect(container.firstChild.firstChild).toHaveComputedStyle({ + paddingTop: '16px', + paddingLeft: '16px', + }); + }); + + it('should use the value from theme and nestable', function test() { + if (/jsdom/.test(window.navigator.userAgent)) { + this.skip(); + } + const { container } = render( + + + + + + + , + ); + expect(container.firstChild).toHaveComputedStyle({ + marginTop: '-16px', + marginLeft: '-16px', + }); + expect(container.firstChild.firstChild).toHaveComputedStyle({ + marginTop: '-12px', + marginLeft: '-12px', + marginRight: '-12px', + marginBottom: '-12px', + paddingTop: '16px', + paddingLeft: '16px', + }); + expect(container.firstChild.firstChild.firstChild).toHaveComputedStyle({ + paddingTop: '12px', + paddingLeft: '12px', + paddingRight: '12px', + paddingBottom: '12px', + }); + }); + }); + describe('Custom breakpoints', () => { it('should apply the custom breakpoint class', () => { const { container } = render( diff --git a/packages/mui-system/src/Unstable_Grid/Grid.tsx b/packages/mui-system/src/Unstable_Grid/Grid.tsx index 97670cb6fb6af8..ffe3f614bb0735 100644 --- a/packages/mui-system/src/Unstable_Grid/Grid.tsx +++ b/packages/mui-system/src/Unstable_Grid/Grid.tsx @@ -56,6 +56,10 @@ Grid.propTypes /* remove-proptypes */ = { PropTypes.arrayOf(PropTypes.oneOf(['column-reverse', 'column', 'row-reverse', 'row'])), PropTypes.object, ]), + /** + * If `true`, the negative margin and padding are apply only to the top and left sides of the grid. + */ + disableEqualOverflow: PropTypes.bool, /** * If a number, it sets the number of columns the grid item uses. * It can't be greater than the total number of columns of the container (12 by default). diff --git a/packages/mui-system/src/Unstable_Grid/GridProps.ts b/packages/mui-system/src/Unstable_Grid/GridProps.ts index 3169d5559da434..f4456f15edafb4 100644 --- a/packages/mui-system/src/Unstable_Grid/GridProps.ts +++ b/packages/mui-system/src/Unstable_Grid/GridProps.ts @@ -137,6 +137,10 @@ export interface GridBaseProps extends Breakpoints { * @default 'row' */ direction?: ResponsiveStyleValue; + /** + * If `true`, the negative margin and padding are apply only to the top and left sides of the grid. + */ + disableEqualOverflow?: boolean; /** * Defines the vertical space between the type `item` components. * It overrides the value of the `spacing` prop. diff --git a/packages/mui-system/src/Unstable_Grid/createGrid.tsx b/packages/mui-system/src/Unstable_Grid/createGrid.tsx index ce3b38eac2e4b1..5a8c0dd7c77270 100644 --- a/packages/mui-system/src/Unstable_Grid/createGrid.tsx +++ b/packages/mui-system/src/Unstable_Grid/createGrid.tsx @@ -58,6 +58,7 @@ export default function createGrid( } = options; const NestedContext = React.createContext(false); + const OverflowContext = React.createContext(undefined); const useUtilityClasses = (ownerState: GridOwnerState, theme: typeof defaultTheme) => { const { container, direction, spacing, wrap, gridSize } = ownerState; @@ -93,6 +94,7 @@ export default function createGrid( const themeProps = useThemeProps(inProps); const props = extendSxProp(themeProps) as Omit; // `color` type conflicts with html color attribute. const nested = React.useContext(NestedContext); + const overflow = React.useContext(OverflowContext); const { className, columns: columnsProp = 12, @@ -103,8 +105,15 @@ export default function createGrid( spacing: spacingProp = 0, rowSpacing: rowSpacingProp = spacingProp, columnSpacing: columnSpacingProp = spacingProp, + disableEqualOverflow: themeDisableEqualOverflow, ...rest } = props; + // `disableEqualOverflow` can be set from theme defaultProps, + // so the **nested** grid does not use it from theme and look at the instance props instead. + let disableEqualOverflow = themeDisableEqualOverflow; + if (nested && themeDisableEqualOverflow !== undefined) { + disableEqualOverflow = inProps.disableEqualOverflow; + } // collect breakpoints related props because they can be custom from the theme. const gridSize = {} as GridOwnerState['gridSize']; const gridOffset = {} as GridOwnerState['gridOffset']; @@ -138,6 +147,8 @@ export default function createGrid( columnSpacing, gridSize, gridOffset, + disableEqualOverflow: disableEqualOverflow ?? overflow ?? false, // use context value if exists. + parentDisableEqualOverflow: overflow, // for nested grid }; const classes = useUtilityClasses(ownerState, theme); @@ -156,6 +167,13 @@ export default function createGrid( result = {result}; } + if (disableEqualOverflow !== undefined && disableEqualOverflow !== (overflow ?? false)) { + // This means the root grid with `disableEqualOverflow` or nested grid with different `disableEqualOverflow` from the context. + result = ( + {result} + ); + } + return result; }) as OverridableComponent; @@ -180,6 +198,7 @@ export default function createGrid( PropTypes.arrayOf(PropTypes.oneOf(['column-reverse', 'column', 'row-reverse', 'row'])), PropTypes.object, ]), + disableEqualOverflow: PropTypes.bool, lg: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.number, PropTypes.bool]), lgOffset: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.number]), md: PropTypes.oneOfType([PropTypes.oneOf(['auto']), PropTypes.number, PropTypes.bool]), diff --git a/packages/mui-system/src/Unstable_Grid/gridGenerator.test.js b/packages/mui-system/src/Unstable_Grid/gridGenerator.test.js index edcc16b8585aea..0319dcb738820a 100644 --- a/packages/mui-system/src/Unstable_Grid/gridGenerator.test.js +++ b/packages/mui-system/src/Unstable_Grid/gridGenerator.test.js @@ -250,6 +250,49 @@ describe('grid generator', () => { padding: `calc(var(--Grid-nested-rowSpacing) / 2) calc(var(--Grid-nested-columnSpacing) / 2)`, }); }); + + it('root container with disableEqualOverflow', () => { + const result = generateGridStyles({ + ownerState: { container: true, nested: true, 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))`, + }); + }); + + it('nested container without disableEqualOverflow but parent has', () => { + const result = generateGridStyles({ + ownerState: { + container: true, + nested: true, + 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))`, + }); + }); + + it('item', () => { + const result = generateGridStyles({ ownerState: { container: false, nested: false } }); + expect(result).to.deep.equal({ + minWidth: 0, + boxSizing: 'border-box', + padding: `calc(var(--Grid-rowSpacing) / 2) calc(var(--Grid-columnSpacing) / 2)`, + }); + }); + + it('item with disableEqualOverflow', () => { + const result = generateGridStyles({ + ownerState: { container: false, disableEqualOverflow: true }, + }); + sinon.assert.match(result, { + padding: `calc(var(--Grid-rowSpacing)) 0px 0px calc(var(--Grid-columnSpacing))`, + }); + }); }); describe('generateGridSizeStyles', () => { diff --git a/packages/mui-system/src/Unstable_Grid/gridGenerator.ts b/packages/mui-system/src/Unstable_Grid/gridGenerator.ts index ea0bb974502c19..2618b42638b5b4 100644 --- a/packages/mui-system/src/Unstable_Grid/gridGenerator.ts +++ b/packages/mui-system/src/Unstable_Grid/gridGenerator.ts @@ -194,9 +194,15 @@ export const generateGridStyles = ({ ownerState }: Props): {} => { 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)', @@ -205,6 +211,9 @@ export const generateGridStyles = ({ ownerState }: Props): {} => { } : { padding: `calc(var(--Grid-rowSpacing) / 2) calc(var(--Grid-columnSpacing) / 2)`, + ...(ownerState.disableEqualOverflow && { + padding: `calc(var(--Grid-rowSpacing)) 0px 0px calc(var(--Grid-columnSpacing))`, + }), }), }; }; From 7a0fc6c80737e66e589de1455d92ac7fa88e8f7f Mon Sep 17 00:00:00 2001 From: siriwatknp Date: Wed, 13 Jul 2022 14:17:40 +0700 Subject: [PATCH 2/5] fix import --- .../system/components/grid/OverflowGrid.js | 2 +- .../system/components/grid/OverflowGrid.tsx | 54 +++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 docs/data/system/components/grid/OverflowGrid.tsx diff --git a/docs/data/system/components/grid/OverflowGrid.js b/docs/data/system/components/grid/OverflowGrid.js index 6d2738ea649cc9..47b49aafed5012 100644 --- a/docs/data/system/components/grid/OverflowGrid.js +++ b/docs/data/system/components/grid/OverflowGrid.js @@ -1,6 +1,6 @@ import * as React from 'react'; import Box from '@mui/system/Box'; -import Grid from '@mui/system/Grid'; +import Grid from '@mui/system/Unstable_Grid'; import styled from '@mui/system/styled'; const Item = styled('div')(({ theme }) => ({ diff --git a/docs/data/system/components/grid/OverflowGrid.tsx b/docs/data/system/components/grid/OverflowGrid.tsx new file mode 100644 index 00000000000000..47b49aafed5012 --- /dev/null +++ b/docs/data/system/components/grid/OverflowGrid.tsx @@ -0,0 +1,54 @@ +import * as React from 'react'; +import Box from '@mui/system/Box'; +import Grid from '@mui/system/Unstable_Grid'; +import styled from '@mui/system/styled'; + +const Item = styled('div')(({ theme }) => ({ + backgroundColor: theme.palette.mode === 'dark' ? '#1A2027' : '#fff', + border: '1px solid', + borderColor: theme.palette.mode === 'dark' ? '#444d58' : '#ced7e0', + padding: theme.spacing(1), + borderRadius: '4px', + textAlign: 'center', +})); + +export default function AutoGrid() { + return ( + ({ + display: 'flex', + flexDirection: 'column', + gap: 3, + '& > div': { + overflow: 'auto hidden', + '&::-webkit-scrollbar': { height: 10, WebkitAppearance: 'none' }, + '&::-webkit-scrollbar-thumb': { + borderRadius: 8, + border: '2px solid', + borderColor: theme.palette.mode === 'dark' ? '' : '#E7EBF0', + backgroundColor: 'rgba(0 0 0 / 0.5)', + }, + }, + })} + > + + + + Scroll bar appears + + + + + + + `disableEqualOverflow` prevents scrollbar + + + + + ); +} From e2766d09aaddd3b6c5afcf2e46a58382a8a04f1a Mon Sep 17 00:00:00 2001 From: siriwatknp Date: Wed, 13 Jul 2022 14:23:13 +0700 Subject: [PATCH 3/5] add comment --- packages/mui-system/src/Unstable_Grid/createGrid.tsx | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/mui-system/src/Unstable_Grid/createGrid.tsx b/packages/mui-system/src/Unstable_Grid/createGrid.tsx index 5a8c0dd7c77270..6123d164bd80d0 100644 --- a/packages/mui-system/src/Unstable_Grid/createGrid.tsx +++ b/packages/mui-system/src/Unstable_Grid/createGrid.tsx @@ -108,13 +108,12 @@ export default function createGrid( disableEqualOverflow: themeDisableEqualOverflow, ...rest } = props; - // `disableEqualOverflow` can be set from theme defaultProps, - // so the **nested** grid does not use it from theme and look at the instance props instead. + // 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) { disableEqualOverflow = inProps.disableEqualOverflow; } - // collect breakpoints related props because they can be custom from the theme. + // collect breakpoints related props because they can be customized from the theme. const gridSize = {} as GridOwnerState['gridSize']; const gridOffset = {} as GridOwnerState['gridOffset']; const other: Record = {}; @@ -168,7 +167,9 @@ export default function createGrid( } if (disableEqualOverflow !== undefined && disableEqualOverflow !== (overflow ?? false)) { - // This means the root grid with `disableEqualOverflow` or nested grid with different `disableEqualOverflow` from the context. + // There are 2 possibilities that should wrap with the OverflowContext to communicate with the nested grids: + // 1. It is the root grid with `disableEqualOverflow`. + // 2. It is a nested grid with different `disableEqualOverflow` from the context. result = ( {result} ); From d811dc09cd1ee01a703448019a647a9cc12cda61 Mon Sep 17 00:00:00 2001 From: Siriwat K Date: Thu, 14 Jul 2022 14:04:31 +0700 Subject: [PATCH 4/5] Update docs/data/system/components/grid/grid.md --- docs/data/system/components/grid/grid.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/data/system/components/grid/grid.md b/docs/data/system/components/grid/grid.md index dedc5828d3b53e..8d8e039a61f70b 100644 --- a/docs/data/system/components/grid/grid.md +++ b/docs/data/system/components/grid/grid.md @@ -156,7 +156,6 @@ declare module '@mui/system' { } ``` -::: ## Prevent scrollbar From 2b9f954b132875079e1a780de15da38c35fb8297 Mon Sep 17 00:00:00 2001 From: Siriwat K Date: Thu, 14 Jul 2022 14:04:52 +0700 Subject: [PATCH 5/5] Update docs/data/system/components/grid/grid.md --- docs/data/system/components/grid/grid.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/data/system/components/grid/grid.md b/docs/data/system/components/grid/grid.md index 8d8e039a61f70b..cb381fe49c509e 100644 --- a/docs/data/system/components/grid/grid.md +++ b/docs/data/system/components/grid/grid.md @@ -156,7 +156,6 @@ declare module '@mui/system' { } ``` - ## Prevent scrollbar If you use grid as a container in a small viewport, you might see a horizontal scrollbar because the negative margin is applied on all sides of the grid container.