Last active
September 18, 2017 04:31
-
-
Save cheton/c89efa8f88e000a47e3dda952060dd85 to your computer and use it in GitHub Desktop.
Show a modal window on the topmost frame of the browser window
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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') | |
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!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