Skip to content

Instantly share code, notes, and snippets.

@petyappetrov
Created February 8, 2019 09:09
Show Gist options
  • Save petyappetrov/248482347ad35e0694243bd833fbc8b0 to your computer and use it in GitHub Desktop.
Save petyappetrov/248482347ad35e0694243bd833fbc8b0 to your computer and use it in GitHub Desktop.
import React, { useState, useEffect } from 'react'
import { createPortal } from 'react-dom'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import { useSpring, animated, config } from 'react-spring'
const Overlay = styled(animated.div)`
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
display: flex;
justify-content: center;
background-color: ${p => p.theme.backgroundColor};
cursor: pointer;
z-index: 11;
`
const Content = styled(animated.div)`
box-shadow: ${p => p.theme.shadow};
margin-top: 160px;
margin-bottom: auto;
flex: 0 1 auto;
width: 640px;
cursor: default;
`
const ModalView = ({ children, isOpen }) => {
if (!isOpen) {
return null
}
const { opacity, transform } = useSpring({
opacity: 1,
transform: 'translate3d(0, 0, 0)',
from: {
opacity: 0,
transform: 'translate3d(0, -40px, 0)'
},
config: (key) => key === 'transform' ? config.wobbly : config.stiff
})
return (
<Overlay style={{ opacity }}>
<Content style={{ transform }}>
{children}
</Content>
</Overlay>
)
}
ModalView.propTypes = {
isOpen: PropTypes.bool.isRequired,
children: PropTypes.node.isRequired
}
const Modal = ({ children }) => {
const [isOpen, setOpen] = useState(false)
const element = document.createElement('div')
const openModal = () => {
setOpen(true)
}
const closeModal = () => {
setOpen(false)
}
const handleKeydown = () => {
if (event.keyCode === 27 && isOpen) {
closeModal()
}
}
useEffect(() => {
document.body.appendChild(element)
document.addEventListener('keydown', handleKeydown)
return () => {
document.body.removeChild(element)
document.removeEventListener('keydown', handleKeydown)
}
})
return children({
closeModal,
openModal,
content: (content) => createPortal(
<ModalView isOpen={isOpen}>,
{content}
</ModalView>,
element
)
})
}
Modal.propTypes = {
children: PropTypes.func.isRequired
}
export default Modal
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment