Open MartinJaskulla opened 3 months ago
What I figured out so far:
There are two relevant lines in node_modules/@emotion/sheet/dist/emotion-sheet.browser.esm.js
.
The first relevant line sets the container the <style>
elements will get added to later. options.container
is the shadowContainer
I passed to createCache
:
this.container = options.container;
The second relevant line adds the <style>
element to the container:
_this.container.insertBefore(tag, before)
If I import Button
from "@mui/material", then both lines are executed from node_modules/@emotion/sheet/dist/emotion-sheet.browser.esm.js
.
If I import from Button
from "reproduction-library", then the first line is executed from node_modules/@emotion/sheet/dist/emotion-sheet.browser.esm.js
, but the second line is executed from my library bundle at node_modules/reproduction-library/dist/main.js
.
How I debugged this:
debugger
statements to node_modules/reproduction-library/dist/main.js
and node_modules/@emotion/sheet/dist/emotion-sheet.browser.esm.js
node_modules/.vite
after every change to the files above e.g. node_modules/reproduction-library/dist/main.js
npm run dev
If I bundle CacheProvider
in my library and then import it from "reproduction-library" instead of "@emotion/react", the problem disappears.
I don't know if this is the recommended approach though. Maybe this should be documented somewhere? As others have stated before, it would be nice to have docs/an example/a template about how to wrap MUI to build your own component library.
Maybe this issue can be closed.
For reference:
In the library:
export * from "@mui/material";
export {CacheProvider} from "@emotion/react"`
Steps to reproduce
Link to live example: https://6698f74d46bade9e76f1d058--guileless-sorbet-bf347d.netlify.app/
https://github.com/MartinJaskulla/reproduction-library https://github.com/MartinJaskulla/reproduction-library-user
<Button>
is unstyled, because emotion style sheets are added to<head>
instead of shadow DOMButton,
and comment in// import {Button} from "@mui/material";
in main.jsxCurrent behavior
<Button>
looks like a native html<button>
inside shadow DOM.Expected behavior
<Button>
should look like a MUI button inside shadow DOM.Context
I created a component library for my company that wraps MUI and makes some adjustments. Everything works flawlessly.
For a new feature we have to use my library inside shadow DOM meaning the project that is installing my component library is creating a custom element and wants to use the wrapped MUI components from my library inside it. I followed the documentation (https://mui.com/material-ui/customization/shadow-dom/) to do that. Somehow the styles do get added to the
<head>
instead of the shadow DOM.I created a new library for my reproduction, in which I just re-export MUI as is (that is the only thing the library is doing): https://github.com/MartinJaskulla/reproduction-library/blob/main/src/main.jsx
If I install this library in a new project (https://github.com/MartinJaskulla/reproduction-library-user), then
import { Button } from "@mui/material";
adds the styles correctly to the shadow DOM, butimport { Button } from "reproduction-library";
adds the styles to the<head>
although the code of both buttons should be identical.To me it looks like MUI only works inside shadow DOM if imported from
"@mui/material";
.Your environment
``` System: OS: macOS 14.5 Binaries: Node: 22.2.0 - /opt/homebrew/bin/node npm: 10.7.0 - /opt/homebrew/bin/npm pnpm: Not Found Browsers: Chrome: 126.0.6478.182 Edge: Not Found Safari: 17.5 ```npx @mui/envinfo
Search keywords: shadowdom library styles emotion