Amar Shah
Amar Shah

Reputation: 87

Material UI component is losing styles inside react-frame-component

I am trying to implement Persistent drawer, available in the demo code in Material UI V3. Link is below https://v3.material-ui.com/demos/drawers/#persistent-drawer

I am wrapping it inside react-frame-component, as I want it as a different iframe. When I am trying to do it, it renders the demo code, but it loses all the Material UI styles.

Code is as below

In PersistentDrawerLeft.jsx (Code is copied from the link given above)

In MainFile.jsx

import React from "react";
import Frame from "react-frame-component";
import PersistentDrawerLeft from "./PersistentDrawerLeft.jsx";

const MainFile = () => {
  
  return (
    <Frame>
        <PersistentDrawerLeft />
    </Frame>
    )
}

export default MainFile;

Could someone please help me out in this.

Upvotes: 2

Views: 3697

Answers (2)

Kim
Kim

Reputation: 61

I have just been experiencing the same issue with a current project but I am using the latest versions. My solution is to use the FrameContextConsumer and inject the jss inside the callback. This example is also defining a new material theme that is distinct from the theme of the frame's parent, you may not need that for your usage.

Here is the link to my sandbox: https://codesandbox.io/s/react-frame-component-with-material-ui-6tqg5

An important consideration to make is when using any Material UI component that has a Modal as a parent (which is quite a few components, including a variant of a Drawer). In my example, I have added a Button that opens a Dialog and on the Dialog the disablePortal property is included. This will ensure the Dialog opens in the frame rather than in the parent where all styles are lost since they were injected into the frame.

import React from "react";
import { create } from "jss";
import { jssPreset } from "@material-ui/core/styles";
import { createMuiTheme } from "@material-ui/core/styles";
import { ThemeProvider, StylesProvider } from "@material-ui/core/styles";
import Frame, { FrameContextConsumer } from "react-frame-component";

const theme = createMuiTheme({
  palette: {
    primary: {
      main: "#556cd6"
    },
    secondary: {
      main: "#19857b"
    },
    background: {
      default: "#dedede",
      paper: "#ffffff"
    }
  }
});

const CustomHead = props => {
  return (
    <>
      <meta charSet="utf-8" />
      <title>Previewer</title>
      <meta name="viewport" content="width=device-width,initial-scale=1" />
      <base target="_parent" />
      <link
        rel="stylesheet"
        href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700&display=swap"
      />
    </>
  );
};

const PreviewFrame = ({ children, ...props }) => {
  return (
    <Frame frameBorder={0} {...props} head={<CustomHead />}>
      <FrameContextConsumer>
        {({ document, window }) => {
          const jss = create({
            plugins: [...jssPreset().plugins],
            insertionPoint: document.head
          });
          return (
            <StylesProvider jss={jss}>
              <ThemeProvider theme={theme}>{children}</ThemeProvider>
            </StylesProvider>
          );
        }}
      </FrameContextConsumer>
    </Frame>
  );
};

export default PreviewFrame;

Upvotes: 6

Gokulakannan T
Gokulakannan T

Reputation: 614

Finally, I have come up with a solution to the problem.

The Problem is,

Every iframe has its own context. The context has its own session history and document. The browsing context that embeds the others is called the parent browsing context which is the browser window object.

The Material UI Style provider can only provide the styles for parent context. So we have to inject the style provider to the iframe context.

The solution is,

The Material UI itself we have a solution for it. The DemoFrame.js is actually injected the StyleProvider to the IFrame context.

Please find the working example in Code Sandbox.

If anybody knows any other better solution. Please suggest in the comment section.

Upvotes: 1

Related Questions