import React, { Fragment } 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(({ ...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: 420px; ${({ 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} ) )} ); }