feature: add Modal component

This commit is contained in:
George Lima 2018-12-19 10:50:08 -03:00
parent 93860eaa93
commit bdb4680057
2 changed files with 99 additions and 2 deletions

98
app/components/modal.js Normal file
View File

@ -0,0 +1,98 @@
// @flow
import React, { PureComponent, Fragment, type Element } from 'react';
import { createPortal } from 'react-dom';
import styled from 'styled-components';
const ModalWrapper = styled.div`
width: 100vw;
height: 100vh;
position: fixed;
display: flex;
align-items: center;
justify-content: center;
top: 0;
left: 0;
z-index: 10;
background-color: rgba(0, 0, 0, 0.4);
`;
const ChildrenWrapper = styled.div`
z-index: 90;
`;
type Props = {
renderTrigger: (() => void) => Element<*>,
children: Element<*>,
};
type State = {
isVisible: boolean,
};
const modalRoot = document.getElementById('modal-root');
export class ModalComponent extends PureComponent<Props, State> {
element = document.createElement('div');
state = {
isVisible: false,
};
componentDidMount() {
window.addEventListener('keydown', this.handleEscPress);
}
componentWillUnmount() {
window.removeEventListener('keydown', this.handleEscPress);
}
handleEscPress = (event: Object) => {
const { isVisible } = this.state;
if (event.key === 'Escape' && isVisible) {
this.close();
}
};
open = () => {
this.setState(
() => ({ isVisible: true }),
() => {
if (modalRoot) modalRoot.appendChild(this.element);
},
);
};
close = () => {
this.setState(
() => ({ isVisible: false }),
() => {
if (modalRoot) modalRoot.removeChild(this.element);
},
);
};
render() {
const { renderTrigger, children } = this.props;
const { isVisible } = this.state;
return (
<Fragment>
{renderTrigger(isVisible ? this.close : this.open)}
{isVisible
? createPortal(
<ModalWrapper
id='modal-portal-wrapper'
onClick={(event) => {
if (event.target.id === 'modal-portal-wrapper') this.close();
}}
>
<ChildrenWrapper>{children}</ChildrenWrapper>
</ModalWrapper>,
this.element,
)
: null}
</Fragment>
);
}
}

View File

@ -13,8 +13,7 @@
<body>
<noscript> You need to enable JavaScript to run this app. </noscript>
<!-- React App Inject -->
<div id="root"></div>
<!-- End React App Inject -->
<div id="modal-root"></div>
</body>
</html>