-
-
Notifications
You must be signed in to change notification settings - Fork 32.6k
[material-nextjs] Add option to enable CSS layers for pages router #45596
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
Changes from all commits
d2ec62b
56b72aa
646056a
fc2d016
19ac097
fe57c42
e36200d
a7af7b5
9c88c09
6373bab
2e811e8
0a76ffd
8c07657
604e862
be1a0fd
1c4785b
5ca6b0f
f1b3a02
9e3645b
7d27586
d333d47
1b56c05
81b2126
50c5f39
0f5d09b
3837d27
8542947
a2f908a
84436db
1c77676
1cfac08
86aafd9
bebad83
55d3241
3f36e9c
2db9972
f1affa3
d76e43a
2900052
e6cabc2
ce472d9
6734245
b10d10d
d38d776
850ce7b
a4f11c6
b79c535
e7de780
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,3 @@ | ||
@tailwind base; | ||
@tailwind components; | ||
@tailwind utilities; | ||
@import 'tailwindcss/theme.css' layer(theme); | ||
@import 'tailwindcss/utilities.css' layer(utilities); | ||
@config '../tailwind.config.mjs'; | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,6 @@ | ||
module.exports = { | ||
plugins: { | ||
'postcss-import': {}, | ||
'tailwindcss/nesting': {}, | ||
tailwindcss: {}, | ||
'@tailwindcss/postcss': {}, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Required for Tailwind CSS v4 |
||
}, | ||
}; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,13 @@ | ||
import createCache from '@emotion/cache'; | ||
import { createEmotionCache as createCache } from '@mui/material-nextjs/v15-pagesRouter'; | ||
import { prefixer } from 'stylis'; | ||
import globalSelector from './modules/utils/globalSelector'; | ||
|
||
export default function createEmotionCache() { | ||
// TODO remove prepend: true once JSS is out | ||
return createCache({ key: 'css', prepend: true, stylisPlugins: [prefixer, globalSelector] }); | ||
return createCache({ | ||
key: 'css', | ||
prepend: true, | ||
enableCssLayer: true, | ||
stylisPlugins: [prefixer, globalSelector], | ||
}); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,16 +2,70 @@ import * as React from 'react'; | |
import { loadCSS } from 'fg-loadcss'; | ||
|
||
/** | ||
* Convenience wrapper around fgLoadCSS for hooks usage | ||
* @param {string} href | ||
* @param {string} before - CSS selector | ||
* Enhanced lazy CSS loader that wraps CSS in a layer using fetch to avoid CORS issues | ||
* @param {string} href - URL of the CSS file to load | ||
* @param {string} before - CSS selector to insert before | ||
* @param {object} options - Additional options | ||
* @param {string} options.layer - Optional CSS layer name to wrap the CSS in | ||
* @returns {() => void} cleanup function | ||
*/ | ||
export default function useLazyCSS(href: string, before: string) { | ||
export default function useLazyCSS(href: string, before: string, options: { layer?: string } = {}) { | ||
React.useEffect(() => { | ||
const link = loadCSS(href, document.querySelector(before) as HTMLElement); | ||
// If no layer is specified, add style and clean it on unmount | ||
if (!options.layer) { | ||
const link = loadCSS(href, document.querySelector(before) as HTMLElement); | ||
return () => { | ||
link.parentElement?.removeChild(link); | ||
}; | ||
} | ||
|
||
// With layer option, we need to fetch the CSS content and wrap it | ||
let styleElement: HTMLStyleElement | null = null; | ||
const abortController = new AbortController(); | ||
|
||
// Fetch the CSS content directly to avoid CORS issues with cssRules | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't understand how we could get CORS issues. Everything comes from the same origin 🤔 But more security do not hurt |
||
fetch(href, { signal: abortController.signal }) | ||
.then((response) => { | ||
if (!response.ok) { | ||
throw new Error(`Failed to fetch CSS: ${response.statusText}`); | ||
} | ||
return response.text(); | ||
}) | ||
.then((cssText) => { | ||
// Create a style element with the CSS wrapped in the specified layer | ||
styleElement = document.createElement('style'); | ||
styleElement.setAttribute('data-href', href); | ||
styleElement.textContent = `@layer ${options.layer} {\n${cssText}\n}`; | ||
|
||
// Insert at the specified position | ||
const beforeElement = document.querySelector(before); | ||
if (beforeElement?.parentNode) { | ||
beforeElement.parentNode.insertBefore(styleElement, beforeElement); | ||
} else { | ||
document.head.appendChild(styleElement); | ||
} | ||
}) | ||
.catch((error) => { | ||
// Ignore abort errors, log others | ||
if (error.name !== 'AbortError') { | ||
if (process.env.NODE_ENV !== 'production') { | ||
console.error('Error loading CSS with layer:', error); | ||
} | ||
|
||
// Fall back to regular link element if fetch fails | ||
styleElement = loadCSS(href, document.querySelector(before) as HTMLElement); | ||
} | ||
}); | ||
|
||
// Cleanup function | ||
return () => { | ||
link.parentElement?.removeChild(link); | ||
// Cancel any pending fetch | ||
abortController.abort(); | ||
|
||
// Remove the style element if it was created | ||
if (styleElement && styleElement.parentElement) { | ||
styleElement.parentElement.removeChild(styleElement); | ||
} | ||
}; | ||
}, [href, before]); | ||
}, [href, before, options.layer]); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,10 +2,10 @@ | |
// eslint-disable-next-line import/no-import-module-exports | ||
import plugin from 'tailwindcss/plugin'; | ||
|
||
const defaultTheme = require('tailwindcss/defaultTheme'); | ||
import defaultTheme from 'tailwindcss/defaultTheme'; | ||
|
||
/** @type {import('tailwindcss').Config} */ | ||
module.exports = { | ||
export default { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Switch to mjs to make the lint passed. |
||
darkMode: ['class', '[data-mui-color-scheme="dark"]'], | ||
content: [ | ||
'./data/**/*.{js,ts,jsx,tsx,mdx}', | ||
|
@@ -55,10 +55,6 @@ module.exports = { | |
}, | ||
}, | ||
}, | ||
corePlugins: { | ||
// Remove the Tailwind CSS preflight styles so it can use Material UI's preflight instead (CssBaseline). | ||
preflight: false, | ||
}, | ||
plugins: [ | ||
plugin(({ addVariant }) => { | ||
[ | ||
|
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.
Based on the Tailwind CSS docs for disabling preflight