Material-ui: Respect Node.ownerDocument of anchorEl when creating portal for Menu

Created on 18 Nov 2017  路  11Comments  路  Source: mui-org/material-ui

  • [x] I have searched the issues of this repository and believe that this is not a duplicate.

Expected Behavior

When opening a Menu and creating a react portal, the portal that's created should reference the Node.ownerDocument of the anchorEl or something similar, to support rendering Material-UI components in a new window (such as through a library like react-popout)

Current Behavior

The portal that is created always uses the global document object to append a portal div to. See: https://github.com/callemall/material-ui/blob/08fae8c2fcd741c01cabbee38305d5ef109acfd5/src/internal/Portal.js#L45-L55

Steps to Reproduce (for bugs)

A simple example can be seen here: https://codesandbox.io/s/v09qklqkj7. You can ignore the lack of styling and what not in the popout window, just trying to show the portal issue.

Your Environment

| Tech | Version |
|--------------|---------|
| Material-UI | 1.0.0-beta.21 |
| React | 16 |
| browser | All |

bug 馃悰 Portal

Most helpful comment

I also ran into this same problem recently. Our project is a Chrome extension, and we render our UI inside of an iframe on the page to avoid inheriting that page's styles, which as you could imagine, breaks the styles added by Material UI in wonderful amazing ways.

This introduced two problems:

  1. JSS injects stylesheets into the top-level document
  2. Material UI Portal renders into the top-level body

We were able to first the first issue by configuring JSS's insertion point to use the iframe's document, but the second issue is exactly what you are addressing with this PR.

I agree that rendering Material UI components into an iframe is an edge-case, but I don't think it should be completely discounted either, as it provides a lot of power when building applications more complicated than a single page application.

All 11 comments

Wow, I wasn't aware of such thing, thanks for sharing! I find it such an edge case that I might never work on fixing it. Have you found a simple work-around?
Maybe something like: https://github.com/react-bootstrap/react-overlays/blob/master/src/Portal.js#L48-L50

Ahh darn i didn't see the link you provided before I started prototyping. Their solution looks very interesting. I'll see if that works well for us and update the PR accordingly.

I also ran into this same problem recently. Our project is a Chrome extension, and we render our UI inside of an iframe on the page to avoid inheriting that page's styles, which as you could imagine, breaks the styles added by Material UI in wonderful amazing ways.

This introduced two problems:

  1. JSS injects stylesheets into the top-level document
  2. Material UI Portal renders into the top-level body

We were able to first the first issue by configuring JSS's insertion point to use the iframe's document, but the second issue is exactly what you are addressing with this PR.

I agree that rendering Material UI components into an iframe is an edge-case, but I don't think it should be completely discounted either, as it provides a lot of power when building applications more complicated than a single page application.

I think the PR (#9236) is in a pretty decent state now.

@corytheboyd do you have a sense if we took the same approach with injecting JSS (respecting Node.ownerDocument), that it might solve your first problem?

@ianschmitz Unfortunately not, the root cause of our JSS issue is not being able to configure the JSS instance that Material UI uses internally. It would be wonderful if you could specify a document through the theme provider (or some other similar provider component) and just have that be the document that the rest of the code references.

I'm currently suffering from an issue somewhat close to what you guys have. So picture a grid system with: left rail, content, and right rail. My left rail container is position: fixed. Inside my left rail I have a tool bar, now each of these toolbar icons use the MUI Popover component which appends to the body. The placement of the popover becomes an issue as the user starts to scroll down the page because what happens is:

1) The scroll shoots right back to the top of the page
2) Then the popover shows up

What I really need is the ability to tell Popover that I would like to inject into a different target other than mui-portal. Or maybe even have a target for mui-portal other than body. Then, I believe, when a user would click on my toolbar the Popover would be positioned relative correctly if I could set a target div of my left rail instead of body.

An example of I'm thinking of is the way Popover works in bootstraphttp://bootstrapdocs.com/v3.0.3/docs/javascript/#popovers where you can specify a 'container' target.

I was searching for answers in the issues and stumbled upon this. @oliviertassinari if you have another way I could solve this I would love to hear. Thanks!

I'm looking into making Material-UI works in an iframe. Has anyone successfully achieve it?

Nevermind, I have found a way :).

@oliviertassinari the tricky part is getting JSS to play nicely. Let me know if you have questions!

I'm on it #13314. JSS insertion point do the job. Now, I need to set the right container for the portal.

Problem solved too :)

capture d ecran 2018-10-20 a 16 25 39

Was this page helpful?
0 / 5 - 0 ratings