Reputation: 87
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
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
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