Skip to content

Instantly share code, notes, and snippets.

@cheton
Last active September 18, 2017 04:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save cheton/c89efa8f88e000a47e3dda952060dd85 to your computer and use it in GitHub Desktop.
Save cheton/c89efa8f88e000a47e3dda952060dd85 to your computer and use it in GitHub Desktop.
Show a modal window on the topmost frame of the browser window
import 'trendmicro-ui/dist/css/trendmicro-ui.css';
import '@trendmicro/react-buttons/dist/react-buttons.css';
import { Button } from '@trendmicro/react-buttons';
import React, { PureComponent } from 'react';
import ReactDOM from 'react-dom';
import styled from 'styled-components';
import Navbar from './Navbar';
import Portal from '../src';
const StyledPortal = styled(Portal)`
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
color: #fff;
background-color: rgba(0, 0, 0, .7);
`;
const VerticallyCenter = styled.div`
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
`;
const Modal = styled.div`
background-color: #fff;
min-width: 360px;
min-height: 240px;
`;
class App extends PureComponent {
state = {
open: false
};
openModal = () => {
this.setState({ open: true });
};
closeModal = () => {
this.setState({ open: false });
};
componentDidMount() {
this.injectStyles();
const target = document.head;
const config = {
attributes: true,
attributeOldValue: false,
characterData: true,
characterDataOldValue: false,
childList: true,
subtree: true
};
this.observer = new MutationObserver(mutations => {
this.removeStyles();
this.injectStyles();
});
this.observer.observe(target, config);
}
removeStyles() {
const parent = window.top;
const head = parent.document.getElementsByTagName('head')[0];
const styles = parent.document.getElementsByTagName('style');
for (let i = 0; i < styles.length; ++i) {
const style = styles[i];
if (style.getAttribute('data-cloned')) {
head.removeChild(styles[i]);
}
}
}
injectStyles() {
const parent = window.top;
const head = parent.document.getElementsByTagName('head')[0];
const styles = document.getElementsByTagName('style');
for (let i = 0; i < styles.length; ++i) {
const clonedStyle = styles[i].cloneNode(true);
clonedStyle.setAttribute('data-cloned', true);
head.appendChild(clonedStyle);
}
}
render() {
const name = 'React Portal';
const url = 'https://github.com/trendmicro-frontend/react-portal';
const { open } = this.state;
return (
<div>
<Navbar name={name} url={url} />
<div className="container-fluid" style={{ marginTop: 10 }}>
{!open &&
<Button onClick={this.openModal}>Open Modal</Button>
}
{open &&
<StyledPortal>
<VerticallyCenter>
<Modal>
<VerticallyCenter>
<h1>Modal Content</h1>
<br />
<div style={{ textAlign: 'center' }}>
<Button onClick={this.closeModal}>Close Modal</Button>
</div>
</VerticallyCenter>
</Modal>
</VerticallyCenter>
</StyledPortal>
}
</div>
</div>
);
}
}
ReactDOM.render(
<App />,
document.getElementById('container')
);
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>React Portal</title>
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
#container {
border: 0;
width: calc(100vw - 40px);
height: calc(100vh - 40px);
}
</style>
</head>
<body style="margin: 0; padding: 20px; background: #666">
<iframe src="./index.html" id="container"></iframe>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment