import React from 'react' import styled, { css } from 'styled-components' import { animated, useTransition, useSpring } from 'react-spring' import { DialogOverlay, DialogContent } from '@reach/dialog' import { isMobile } from 'react-device-detect' import '@reach/dialog/styles.css' import { transparentize } from 'polished' import { useGesture } from 'react-use-gesture' const AnimatedDialogOverlay = animated(DialogOverlay) // eslint-disable-next-line @typescript-eslint/no-unused-vars const StyledDialogOverlay = styled(AnimatedDialogOverlay)` &[data-reach-dialog-overlay] { z-index: 2; background-color: transparent; overflow: hidden; display: flex; align-items: center; justify-content: center; background-color: ${({ theme }) => theme.modalBG}; } ` const AnimatedDialogContent = animated(DialogContent) // destructure to not pass custom props to Dialog DOM element // eslint-disable-next-line @typescript-eslint/no-unused-vars const StyledDialogContent = styled(({ minHeight, maxHeight, mobile, isOpen, ...rest }) => ( )).attrs({ 'aria-label': 'dialog', })` overflow-y: ${({ mobile }) => (mobile ? 'scroll' : 'hidden')}; &[data-reach-dialog-content] { margin: 0 0 2rem 0; background-color: ${({ theme }) => theme.bg0}; border: 1px solid ${({ theme }) => theme.bg1}; box-shadow: 0 4px 8px 0 ${({ theme }) => transparentize(0.95, theme.shadow1)}; padding: 0px; width: 50vw; overflow-y: ${({ mobile }) => (mobile ? 'scroll' : 'hidden')}; overflow-x: hidden; align-self: ${({ mobile }) => (mobile ? 'flex-end' : 'center')}; max-width: 500px; ${({ maxHeight }) => maxHeight && css` max-height: ${maxHeight}vh; `} ${({ minHeight }) => minHeight && css` min-height: ${minHeight}vh; `} display: flex; border-radius: 20px; ${({ theme }) => theme.mediaWidth.upToMedium` width: 65vw; margin: 0; `} ${({ theme, mobile }) => theme.mediaWidth.upToSmall` width: 85vw; ${ mobile && css` width: 100vw; border-radius: 20px; border-bottom-left-radius: 0; border-bottom-right-radius: 0; ` } `} } ` interface ModalProps { isOpen: boolean onDismiss: () => void minHeight?: number | false maxHeight?: number initialFocusRef?: React.RefObject children?: React.ReactNode } export default function Modal({ isOpen, onDismiss, minHeight = false, maxHeight = 90, initialFocusRef, children, }: ModalProps) { const fadeTransition = useTransition(isOpen, null, { config: { duration: 200 }, from: { opacity: 0 }, enter: { opacity: 1 }, leave: { opacity: 0 }, }) const [{ y }, set] = useSpring(() => ({ y: 0, config: { mass: 1, tension: 210, friction: 20 } })) const bind = useGesture({ onDrag: (state) => { set({ y: state.down ? state.movement[1] : 0, }) if (state.movement[1] > 300 || (state.velocity > 3 && state.direction[1] > 0)) { onDismiss() } }, }) return ( <> {fadeTransition.map( ({ item, key, props }) => item && ( `translateY(${(y as number) > 0 ? y : 0}px)`) }, } : {})} aria-label="dialog content" minHeight={minHeight} maxHeight={maxHeight} mobile={isMobile} > {/* prevents the automatic focusing of inputs on mobile by the reach dialog */} {!initialFocusRef && isMobile ?
: null} {children} ) )} ) }