Material-ui: Support Shadow DOM

Created on 18 Sep 2019  路  31Comments  路  Source: mui-org/material-ui

Issue:

When integrating modal or date picker or popover inside Shadow DOM, the click away listener is not working.

Expected Behavior:

On clicking outside, should close the modal, popover or the date picker

Current Behavior:

On clicking outside, the modal, popover or the date picker stays the same without closing.

A sample code:
Code sandbox

I need this to be fixed as soon as possible for one of my projects. Please help.

enhancement waiting for 馃憤

Most helpful comment

I have added the waiting for users upvotes tag. I'm closing the issue as we are not sure enough people are looking for such support. So please upvote this issue if you are. We will prioritize our effort based on the number of upvotes.

All 31 comments

Hello @oliviertassinari,

I found a workaround to fix this issue. Please let me know if you need code sandbox for a sample.
https://stackoverflow.com/questions/57984666/reactjs-material-ui-clickawaylistener-is-not-working-properly-in-the-shadow

Thanks for sharing.

This is partly an upstream bug of React. Fix is already drafted. https://github.com/facebook/react/pull/15894

@Jack-Works Thank you!

@oliviertassinari I noticed one more issue:

Unable to focus on input boxes

Steps to reproduce:

  • Create an Input inside a Modal
  • Put that modal inside a shadow DOM
  • Now every time you click on the text field inside the modal, it closes the modal and never focuses.

Everyone have this issue please leave a comment for your usage on https://github.com/facebook/react/pull/15894 you can see Facebook doesn't have any action on that pr.

And does hack on https://github.com/mui-org/material-ui/issues/16223#issuecomment-501998103 solves your problem?

@Jack-Works Yes, it works but focusing on inputs is not functioning inside the shadow dom.

I have added the waiting for users upvotes tag. I'm closing the issue as we are not sure enough people are looking for such support. So please upvote this issue if you are. We will prioritize our effort based on the number of upvotes.

Please consider adding support for shadow DOM

Do you guys have more details on why shadow DOM? It will help better understand the need. What's the objective of it? For instance, if it's isolation, how is it solving more problems than creating?

Our project is a browser extension, we need to inject UI into other web pages so we choose ShadowDOM.

Currently, React, JSS and @material-ui don't support Shadow DOM well so we did a lot of hacks to make it work.

@Jack-Works Have you considered to increase the CSS specificity of the styles (can be done with a JSS pluggin, say to 10) over using shadow DOM? What's that limitations of iframe?

@Jack-Works Have you considered to increase the CSS specificity of the styles (can be done with a JSS pluggin, say to 10) over using shadow DOM? What's that limitations of iframe?

It's not the problem of css priority. We need to hide the Dom we added to the webpage so the webpage cannot see any text we added to the page.

@Jack-Works Did you notice improvement opportunities from our side? I'm especially interested in the diff between the work that is required between having to React work in shadow DOM (this is outside of our scope) and the work required to make Material-UI work in shadow DOM. Basically, what can we do here to help the process? I have never looked at it in details, my distant perception on the matter is that React doesn't do any effort for the use case.

Yes, IIRC in @material-ui there's some code assuming it is running in the main dom (maybe related to Modal) then it becomes buggy.

Anyway, the most important part is I want to let JSS support ShadowDOM but I think it's not the duty of @material-ui.

I also tried to contribute to React to improve the support for ShadowDOM but they don't accept it until now.

We're using disableAutoFocus of Modal in our project, cause it's buggy in the ShadowDOM

disableAutoFocus might have been solved with https://github.com/mui-org/material-ui/pull/20694/files#diff-0e78f960bb89a643a4ed56411c35db66R71

What about JSS? It would be nice to let JSS support inject style tags into ShadowRoot, even https://developers.google.com/web/updates/2019/02/constructable-stylesheets this modern feature!

You can inject the styles where ever you want with JSS (insertionPoint).

Our code are multiple root (all of those root are in the ShadowRoot) React application so I have no idea if insertionPoint will work for us, but thanks I'll try it later.

cc @NMinhNguyen in case you have any insight on this one. I recall your team tried Shadow DOM at some point.

Our code are multiple root (all of those root are in the ShadowRoot) React application so I have no idea if insertionPoint will work for us, but thanks I'll try it later.

You'd need an insertionPoint per shadow DOM root.

Our code are multiple root (all of those root are in the ShadowRoot) React application so I have no idea if insertionPoint will work for us, but thanks I'll try it later.

You'd need an insertionPoint per shadow DOM root.

Hmm maybe I'm not clear. We have multiple root. Each root is in a separate ShadowDOM so it's required to have insertionPoint for every root.

Our code are multiple root (all of those root are in the ShadowRoot) React application so I have no idea if insertionPoint will work for us, but thanks I'll try it later.

You'd need an insertionPoint per shadow DOM root.

Hmm maybe I'm not clear. We have multiple root. Each root is in a separate ShadowDOM so it's required to have insertionPoint for every root.

Sounds like we're saying the same thing? You're supposed to use a StylesProvider inside each root which would have its own insertion point https://material-ui.com/styles/advanced/#insertionpoint

@oliviertassinari

Do you guys have more details on why shadow DOM? It will help better understand the need. What's the objective of it? For instance, if it's isolation, how is it solving more problems than creating?

Sure. I love material ui and I build almost all of my projects with it. Recently, I was building an embeddable widget. So if I make it in shadow DOM, none of the styles would apply to MUI components inside of it. Without the shadow DOM, there can be a few conflicts with webpage styles.

Regarding the part about avoiding CSS conflicts when injecting in a hostile environment: #19455.

Unluckily we got this: Warning: [JSS] Insertion point is not in the DOM.聽

So we have to hack the ShadowRoot:

new Proxy(this.props.shadow as any, {
        get(target, property: keyof ShadowRoot) {
            if (property === 'parentNode') {
                const host = target.getRootNode({ composed: true })
                if (host !== document) {
                    return null
                }
                return target
            }
            return target[property]
        },
    })

And without the hack I mentioned above, JSS won't render stylesheets

Another problem: when we want to render Dialogs in another shadow root, it seems not possible to have a simple way to clone all the style tags we need into another Shadow Root.

Was this page helpful?
0 / 5 - 0 ratings