From 13096fa41e7d9ca61afe64effd9188bdd9cd0dfd Mon Sep 17 00:00:00 2001 From: Brijesh Bittu Date: Tue, 30 Apr 2024 15:37:04 +0530 Subject: [PATCH] [system][enhancement] Dedupe zero min width media queries from the generated css. These don't have any higher specificity than direct css. Fixes #42025 --- packages/mui-system/src/Stack/Stack.test.js | 76 ++++++++----------- .../mui-system/src/breakpoints/breakpoints.js | 10 +++ .../src/breakpoints/breakpoints.test.js | 12 ++- .../styleFunctionSx/styleFunctionSx.test.js | 38 +++++----- 4 files changed, 63 insertions(+), 73 deletions(-) diff --git a/packages/mui-system/src/Stack/Stack.test.js b/packages/mui-system/src/Stack/Stack.test.js index 85649885796bb0..c3124353acf18e 100644 --- a/packages/mui-system/src/Stack/Stack.test.js +++ b/packages/mui-system/src/Stack/Stack.test.js @@ -29,14 +29,11 @@ describe('', () => { theme, }), ).to.deep.equal({ - '@media (min-width:0px)': { - '& > :not(style):not(style)': { - margin: 0, - }, - '& > :not(style) ~ :not(style)': { - marginTop: '8px', - }, - flexDirection: 'column', + '& > :not(style):not(style)': { + margin: 0, + }, + '& > :not(style) ~ :not(style)': { + marginTop: '8px', }, [`@media (min-width:${theme.breakpoints.values.sm}px)`]: { '& > :not(style):not(style)': { @@ -194,14 +191,11 @@ describe('', () => { theme, }), ).to.deep.equal({ - '@media (min-width:0px)': { - '& > :not(style):not(style)': { - margin: 0, - }, - '& > :not(style) ~ :not(style)': { - marginTop: '8px', - }, - flexDirection: 'column', + '& > :not(style):not(style)': { + margin: 0, + }, + '& > :not(style) ~ :not(style)': { + marginTop: '8px', }, [`@media (min-width:${theme.breakpoints.values.lg}px)`]: { '& > :not(style):not(style)': { @@ -248,14 +242,11 @@ describe('', () => { theme, }), ).to.deep.equal({ - '@media (min-width:0px)': { - '& > :not(style):not(style)': { - margin: 0, - }, - '& > :not(style) ~ :not(style)': { - marginTop: '8px', - }, - flexDirection: 'column', + '& > :not(style):not(style)': { + margin: 0, + }, + '& > :not(style) ~ :not(style)': { + marginTop: '8px', }, [`@media (min-width:${theme.breakpoints.values.sm}px)`]: { '& > :not(style):not(style)': { @@ -306,13 +297,11 @@ describe('', () => { theme, }), ).to.deep.equal({ - [`@media (min-width:${theme.breakpoints.values.xs}px)`]: { - '& > :not(style):not(style)': { - margin: 0, - }, - '& > :not(style) ~ :not(style)': { - marginTop: '0px', - }, + '& > :not(style):not(style)': { + margin: 0, + }, + '& > :not(style) ~ :not(style)': { + marginTop: '0px', }, [`@media (min-width:${theme.breakpoints.values.md}px)`]: { '& > :not(style):not(style)': { @@ -352,13 +341,11 @@ describe('', () => { theme, }), ).to.deep.equal({ - [`@media (min-width:${theme.breakpoints.values.xs}px)`]: { - '& > :not(style):not(style)': { - margin: 0, - }, - '& > :not(style) ~ :not(style)': { - marginTop: '0px', - }, + '& > :not(style):not(style)': { + margin: 0, + }, + '& > :not(style) ~ :not(style)': { + marginTop: '0px', }, [`@media (min-width:${theme.breakpoints.values.sm}px)`]: { '& > :not(style):not(style)': { @@ -411,13 +398,11 @@ describe('', () => { theme, }), ).to.deep.equal({ - '@media (min-width:0px)': { - '& > :not(style):not(style)': { - margin: 0, - }, - '& > :not(style) ~ :not(style)': { - marginTop: '8px', - }, + '& > :not(style):not(style)': { + margin: 0, + }, + '& > :not(style) ~ :not(style)': { + marginTop: '8px', }, [`@media (min-width:${theme.breakpoints.values.sm}px)`]: { '& > :not(style):not(style)': { @@ -518,7 +503,6 @@ describe('', () => { }); const keysForResponsiveStyles = Object.keys(styles).filter((prop) => prop.includes('@media')); expect(keysForResponsiveStyles).to.deep.equal([ - '@media (min-width:0px)', '@media (min-width:900px)', '@media (min-width:1200px)', '@media (min-width:1536px)', diff --git a/packages/mui-system/src/breakpoints/breakpoints.js b/packages/mui-system/src/breakpoints/breakpoints.js index ee98789726298e..0d1d40bfa73008 100644 --- a/packages/mui-system/src/breakpoints/breakpoints.js +++ b/packages/mui-system/src/breakpoints/breakpoints.js @@ -121,10 +121,20 @@ export function createEmptyBreakpointObject(breakpointsInput = {}) { export function removeUnusedBreakpoints(breakpointKeys, style) { return breakpointKeys.reduce((acc, key) => { + const zeroMediaQueryRgx = /^@media\s\(min-width:\s?[0]([a-zA-Z]{2,3})\)$/; const breakpointOutput = acc[key]; const isBreakpointUnused = !breakpointOutput || Object.keys(breakpointOutput).length === 0; if (isBreakpointUnused) { delete acc[key]; + } else if (zeroMediaQueryRgx.test(key)) { + const zeroMediaValues = acc[key]; + delete acc[key]; + // Zero media query is always at the top, so it's safe to assume that there are no keys before + // it and we can directly spread zero media query styles before other media queries. + acc = { + ...zeroMediaValues, + ...acc, + }; } return acc; }, style); diff --git a/packages/mui-system/src/breakpoints/breakpoints.test.js b/packages/mui-system/src/breakpoints/breakpoints.test.js index 2f54f6b738c763..ff0897b5db7835 100644 --- a/packages/mui-system/src/breakpoints/breakpoints.test.js +++ b/packages/mui-system/src/breakpoints/breakpoints.test.js @@ -259,13 +259,11 @@ describe('breakpoints', () => { }, ); expect(result).to.deep.equal({ - '@media (min-width:0px)': { - fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', - fontSize: '0.875rem', - letterSpacing: '0.01071em', - fontWeight: 400, - lineHeight: 1.43, - }, + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + fontSize: '0.875rem', + letterSpacing: '0.01071em', + fontWeight: 400, + lineHeight: 1.43, }); }); }); diff --git a/packages/mui-system/src/styleFunctionSx/styleFunctionSx.test.js b/packages/mui-system/src/styleFunctionSx/styleFunctionSx.test.js index d8ca1d7a8e778e..7e6799a8ca2a00 100644 --- a/packages/mui-system/src/styleFunctionSx/styleFunctionSx.test.js +++ b/packages/mui-system/src/styleFunctionSx/styleFunctionSx.test.js @@ -86,7 +86,7 @@ describe('styleFunctionSx', () => { '@media print': { display: 'block', }, - '@media (min-width:0px)': { border: '1px solid' }, + border: '1px solid', '@media (min-width:600px)': { border: '2px solid' }, '@media (min-width:960px)': { border: '3px solid' }, '@media (min-width:1280px)': { border: '4px solid' }, @@ -101,13 +101,11 @@ describe('styleFunctionSx', () => { }); expect(result).to.deep.equal({ - '@media (min-width:0px)': { - fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', - fontSize: `${14 / 16}rem`, - letterSpacing: `${round(0.15 / 14)}em`, - fontWeight: 400, - lineHeight: 1.43, - }, + fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', + fontSize: `${14 / 16}rem`, + letterSpacing: `${round(0.15 / 14)}em`, + fontWeight: 400, + lineHeight: 1.43, '@media (min-width:600px)': { fontFamily: '"Roboto", "Helvetica", "Arial", sans-serif', fontSize: '1rem', @@ -154,12 +152,10 @@ describe('styleFunctionSx', () => { background: 'rgb(0, 0, 255)', '&:hover': { backgroundColor: 'rgb(0, 0, 255)', - '@media (min-width:0px)': { - opacity: 0.1, - border: '1px solid', - borderColor: 'rgb(0, 255, 0)', - translate: 'transform(10px)', - }, + opacity: 0.1, + border: '1px solid', + borderColor: 'rgb(0, 255, 0)', + translate: 'transform(10px)', '@media (min-width:600px)': { opacity: 0.2, border: '2px solid', @@ -175,7 +171,7 @@ describe('styleFunctionSx', () => { describe('breakpoints', () => { const breakpointsExpectedResult = { - '@media (min-width:0px)': { border: '1px solid' }, + border: '1px solid', '@media (min-width:600px)': { border: '2px solid' }, '@media (min-width:960px)': { border: '3px solid' }, '@media (min-width:1280px)': { border: '4px solid' }, @@ -215,7 +211,8 @@ describe('styleFunctionSx', () => { }); expect(result).to.deep.equal({ - '@media (min-width:0px)': { padding: '50px', margin: '10px' }, + padding: '50px', + margin: '10px', '@media (min-width:600px)': { padding: '60px', margin: '20px' }, '@media (min-width:960px)': { padding: '70px', margin: '30px' }, }); @@ -229,14 +226,14 @@ describe('styleFunctionSx', () => { // Test the order expect(Object.keys(result)).to.deep.equal([ - '@media (min-width:0px)', + 'padding', '@media (min-width:600px)', '@media (min-width:960px)', '@media (min-width:1280px)', ]); expect(result).to.deep.equal({ - '@media (min-width:0px)': { padding: '0px' }, + padding: '0px', '@media (min-width:600px)': { padding: '10px' }, '@media (min-width:960px)': { padding: '20px', margin: '10px' }, '@media (min-width:1280px)': { margin: '20px' }, @@ -454,14 +451,15 @@ describe('styleFunctionSx', () => { expect(result).to.deep.equal([ { - '@media (min-width:0px)': { border: '1px solid' }, + border: '1px solid', '@media (min-width:600px)': { border: '2px solid' }, '@media (min-width:960px)': { border: '3px solid' }, '@media (min-width:1280px)': { border: '4px solid' }, '@media (min-width:1920px)': { border: '5px solid' }, }, { - '@media (min-width:0px)': { padding: '50px', margin: '10px' }, + padding: '50px', + margin: '10px', '@media (min-width:600px)': { padding: '60px', margin: '20px' }, '@media (min-width:960px)': { padding: '70px', margin: '30px' }, },