Skip to content

Instantly share code, notes, and snippets.

@condor-bird
Last active April 22, 2018 11:16
Show Gist options
  • Save condor-bird/3b8c683621cc50bb56316b2f3f46f881 to your computer and use it in GitHub Desktop.
Save condor-bird/3b8c683621cc50bb56316b2f3f46f881 to your computer and use it in GitHub Desktop.
React modal popup example
body {
background-color: #1B2B34;
font-size: 62.5%;
font-family: sans-serif;
color: #00273B;
}
.app-cont {
display: flex;
justify-content: center;
height: calc(100vh - 1.25rem);
width: 100%;
border: 0.1rem solid #CCD4D8;
border-radius: 0.2rem;
background-color: #EEE;
}
.app-cont .__center {
align-self: center;
font-size: 1.5rem;
text-align: center;
}
.app-cont .__center .__btn {
padding: .75rem 1.25rem;
background-color: #278FBB;
border-radius: 0.2rem;
border: none;
color: #FFF;
cursor: pointer;
}
.app-cont .__center .__btn:hover {
background-color: #379CC7;
}
.modal-wrapper {
display: flex;
flex-direction: column;
align-items: center;
height: 100%;
}
.modal-wrapper .insult {
flex: 1;
font-size: 1.4rem;
color: red;
}
.modal-wrapper button:first-of-type {
margin-right: 1rem;
}
#modal-container {
display: none;
}
#modal-container.active {
display: block;
}
#modal-container .overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100vh;
background-color: #000;
opacity: .7;
z-index: 1;
}
#modal-container .modal {
position: absolute;
top: 0;
left: 0;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100vh;
z-index: 2;
}
#modal-container .modal .modal-content {
width: 50%;
height: 50%;
padding: 1rem;
border-radius: 0.2rem;
background-color: #FFF;
opacity: 1;
}
<body>
<div id="app"></div>
</body>
class MainApp extends React.Component {
constructor(...args) {
super(...args);
this.state = {
isModalActive: false,
isModalAppendable: true
};
this.activateModal = this.activateModal.bind(this);
this.deactivateModal = this.deactivateModal.bind(this);
this.unmountModal = this.unmountModal.bind(this);
}
activateModal(){
this.setState({
isModalActive: true
});
}
deactivateModal(){
this.setState({
isModalActive: false
});
}
unmountModal(){
this.setState({
isModalActive: false,
isModalAppendable: false
});
}
render(){
//this ugly hunk of trash determines if we should unmount the component by returning the right things
let modal = this.state.isModalAppendable
? (<Modal isActive={this.state.isModalActive} closeModal={this.deactivateModal}>
<div className='modal-wrapper'>
<div className='insult'>And he doesn't have that many.....</div>
<div className='button-row'>
<button onClick={this.deactivateModal}>Close modal bruh</button>
<button onClick={this.unmountModal}>Close modal and unmount component bruh</button>
</div>
</div>
</Modal>)
: null;
return (
<div className={'app-cont'}>
<span className={'__center'}>
<CenterDiv activateModal={this.activateModal} />
{modal}
</span>
</div>
);
}
}
class Modal extends React.Component {
constructor(...args){
super(...args);
this.handleClickInside = this.handleClickInside.bind(this);
this.handleClickOutside = this.handleClickOutside.bind(this);
}
componentDidMount(){
//create an element to append
this.modal = document.createElement('div');
//append that shit
document.body.appendChild(this.modal);
//call the render method to add custom styled div and children contents to appended element
this.renderModalContent(this.props);
}
componentWillReceiveProps(newProps){
this.renderModalContent(newProps);
}
componentWillUnmount(){
//act like this shit was never here ever
ReactDOM.unmountComponentAtNode(this.modal);
document.body.removeChild(this.modal);
}
handleClickInside(e){
e.stopPropagation();
}
handleClickOutside(){
this.props.closeModal();
}
renderModalContent(props){
//put something in the appended shit
let cont;
ReactDOM.render(
<div id='modal-container'>
<div className='overlay'></div>
<div className='modal' onClick={this.handleClickOutside}>
<div className='modal-content' onClick={this.handleClickInside}>
{this.props.children}
</div>
</div>
</div>,
this.modal
);
cont = document.getElementById('modal-container');
if (props.isActive){
cont.classList.add('active');
} else {
cont.classList.remove('active');
}
}
render(){
//don't render anything here because we are appending to the body portal style ahhhh yissssss
return null;
}
}
const CenterDiv = (props) => {
return (
<div>
<span>JRU is a jerk that doesn't like his friends.</span><br />
<button className='__btn' onClick={props.activateModal}>PUSH ME</button>
</div>
);
};
ReactDOM.render(<MainApp />, document.getElementById('app'));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment