Skip to content
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

Styles not added to shadow DOM when wrapping MUI in a library #42992

Open
MartinJaskulla opened this issue Jul 18, 2024 · 2 comments
Open

Styles not added to shadow DOM when wrapping MUI in a library #42992

MartinJaskulla opened this issue Jul 18, 2024 · 2 comments
Assignees
Labels
external dependency Blocked by external dependency, we can’t do anything about it package: system Specific to @mui/system

Comments

@MartinJaskulla
Copy link

MartinJaskulla commented Jul 18, 2024

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

  1. git clone https://github.com/MartinJaskulla/reproduction-library-user
  2. npm i
  3. npm run dev
  4. See the bug: MUI <Button> is unstyled, because emotion style sheets are added to <head> instead of shadow DOM
  5. Comment out Button, and comment in // import {Button} from "@mui/material"; in main.jsx
  6. Bug gone

Current 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

export * from "@mui/material";

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, but import { 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

npx @mui/envinfo
 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

Search keywords: shadowdom library styles emotion

@MartinJaskulla MartinJaskulla added the status: waiting for maintainer These issues haven't been looked at yet by a maintainer label Jul 18, 2024
@zannager zannager added the package: system Specific to @mui/system label Jul 18, 2024
@MartinJaskullaTS
Copy link

MartinJaskullaTS commented Jul 19, 2024

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:

  • Add debugger statements to node_modules/reproduction-library/dist/main.js and node_modules/@emotion/sheet/dist/emotion-sheet.browser.esm.js
  • Delete node_modules/.vite after every change to the files above e.g. node_modules/reproduction-library/dist/main.js
  • Restart npm run dev
  • Remove node_modules from debugger ignore list:
Screenshot 2024-07-19 at 13 36 09 Screenshot 2024-07-19 at 13 35 11

@MartinJaskullaTS
Copy link

MartinJaskullaTS commented Jul 19, 2024

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"`

@siriwatknp siriwatknp added external dependency Blocked by external dependency, we can’t do anything about it and removed status: waiting for maintainer These issues haven't been looked at yet by a maintainer labels Aug 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
external dependency Blocked by external dependency, we can’t do anything about it package: system Specific to @mui/system
Projects
None yet
Development

No branches or pull requests

5 participants