diff --git a/app/components/dropdown.js b/app/components/dropdown.js index 59c9101..a2f17d1 100644 --- a/app/components/dropdown.js +++ b/app/components/dropdown.js @@ -90,7 +90,7 @@ export class DropdownComponent extends Component { )} {options.map(({ label: optionLabel, onClick }) => ( - + ))} diff --git a/app/components/modal.js b/app/components/modal.js new file mode 100644 index 0000000..63493ef --- /dev/null +++ b/app/components/modal.js @@ -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 { + 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 ( + + {renderTrigger(isVisible ? this.close : this.open)} + {isVisible + ? createPortal( + { + if (event.target.id === 'modal-portal-wrapper') this.close(); + }} + > + {children} + , + this.element, + ) + : null} + + ); + } +} diff --git a/app/components/transaction-daily.js b/app/components/transaction-daily.js index 68a3cd7..db37d7f 100644 --- a/app/components/transaction-daily.js +++ b/app/components/transaction-daily.js @@ -1,5 +1,5 @@ // @flow -import React from 'react'; +import React, { Fragment } from 'react'; import styled from 'styled-components'; import { TransactionItemComponent, type Transaction } from './transaction-item'; import { TextComponent } from './text'; @@ -49,7 +49,7 @@ export const TransactionDailyComponent = ({ {transactions.map(({ date, type, address, amount, }, idx) => ( -
+ {idx < transactions.length - 1 && } -
+ ))} diff --git a/public/index.html b/public/index.html index 676487b..311e933 100644 --- a/public/index.html +++ b/public/index.html @@ -13,8 +13,7 @@ -
- +