From e16f0f554718c72e9db1c4bb187641df1b071c54 Mon Sep 17 00:00:00 2001 From: Siriwat K Date: Mon, 23 Dec 2024 10:28:52 +0700 Subject: [PATCH] [system] set `before` directly without using prepend for global styles (#44648) --- .../StyledEngineProvider.js | 45 ++++++++++++------- .../fixtures/GlobalStyles/InjectFirst.js | 16 +++++++ 2 files changed, 44 insertions(+), 17 deletions(-) create mode 100644 test/regressions/fixtures/GlobalStyles/InjectFirst.js diff --git a/packages/mui-styled-engine/src/StyledEngineProvider/StyledEngineProvider.js b/packages/mui-styled-engine/src/StyledEngineProvider/StyledEngineProvider.js index 13c74493ecc868..6a0a722ee25981 100644 --- a/packages/mui-styled-engine/src/StyledEngineProvider/StyledEngineProvider.js +++ b/packages/mui-styled-engine/src/StyledEngineProvider/StyledEngineProvider.js @@ -7,23 +7,11 @@ import { StyleSheet } from '@emotion/sheet'; // We might be able to remove this when this issue is fixed: // https://github.com/emotion-js/emotion/issues/2790 -const createEmotionCache = (options) => { +const createEmotionCache = (options, CustomSheet) => { const cache = createCache(options); - /** - * This is for client-side apps only. - * A custom sheet is required to make the GlobalStyles API work with `prepend: true`. - * This is because the [sheet](https://github.com/emotion-js/emotion/blob/main/packages/react/src/global.js#L94-L99) does not consume the options. - */ - class MyStyleSheet extends StyleSheet { - constructor(args) { - super(args); - this.prepend = cache.sheet.prepend; - } - } - // Do the same as https://github.com/emotion-js/emotion/blob/main/packages/cache/src/index.js#L238-L245 - cache.sheet = new MyStyleSheet({ + cache.sheet = new CustomSheet({ key: cache.key, nonce: cache.sheet.nonce, container: cache.sheet.container, @@ -35,11 +23,34 @@ const createEmotionCache = (options) => { return cache; }; -// prepend: true moves MUI styles to the top of the so they're loaded first. -// It allows developers to easily override MUI styles with other styling solutions, like CSS modules. let cache; if (typeof document === 'object') { - cache = createEmotionCache({ key: 'css', prepend: true }); + // Use `insertionPoint` over `prepend`(deprecated) because it can be controlled for GlobalStyles injection order + // For more information, see https://github.com/mui/material-ui/issues/44597 + let insertionPoint = document.querySelector('[name="emotion-insertion-point"]'); + if (!insertionPoint) { + insertionPoint = document.createElement('meta'); + insertionPoint.setAttribute('name', 'emotion-insertion-point'); + insertionPoint.setAttribute('content', ''); + const head = document.querySelector('head'); + if (head) { + head.prepend(insertionPoint); + } + } + /** + * This is for client-side apps only. + * A custom sheet is required to make the GlobalStyles API injected above the insertion point. + * This is because the [sheet](https://github.com/emotion-js/emotion/blob/main/packages/react/src/global.js#L94-L99) does not consume the options. + */ + class MyStyleSheet extends StyleSheet { + insert(rule, options) { + if (this.key && this.key.endsWith('global')) { + this.before = insertionPoint; + } + return super.insert(rule, options); + } + } + cache = createEmotionCache({ key: 'css', insertionPoint }, MyStyleSheet); } export default function StyledEngineProvider(props) { diff --git a/test/regressions/fixtures/GlobalStyles/InjectFirst.js b/test/regressions/fixtures/GlobalStyles/InjectFirst.js new file mode 100644 index 00000000000000..3630eaca8bc5b8 --- /dev/null +++ b/test/regressions/fixtures/GlobalStyles/InjectFirst.js @@ -0,0 +1,16 @@ +import * as React from 'react'; +import { StyledEngineProvider } from '@mui/material/styles'; +import CssBaseline from '@mui/material/CssBaseline'; +import GlobalStyles from '@mui/material/GlobalStyles'; +import Typography from '@mui/material/Typography'; + +export default function InjectFirst() { + return ( + + + Hello MUI v6 + The color should be red + ({ body: { color: 'red' } })} /> + + ); +}