import { Z_INDICES } from '@past3lle/constants'
import { useIsMobile } from '@past3lle/hooks'
import { upToExtraSmall } from '@past3lle/theme'
import { DialogContent, DialogOverlay } from '@reach/dialog'
import { transparentize } from 'polished'
import React, { useEffect } from 'react'
import { animated } from 'react-spring'
import styled from 'styled-components'
const AnimatedDialogOverlay = animated(DialogOverlay)
interface ModalStyleProps {
overlayBackgroundColor?: string
zIndex?: number
boxShadowColor?: string
mainBackgroundColor?: string
}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const StyledDialogOverlay = styled(({ zIndex, ...props }) => )<
Pick
>`
&[data-reach-dialog-overlay] {
z-index: ${({ zIndex = Z_INDICES.MODALS }) => zIndex};
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: transparent;
overflow: hidden;
display: flex;
align-items: center;
justify-content: center;
background-color: ${({ overlayBackgroundColor = 'rgba(0,0,0,0.7)' }) => overlayBackgroundColor};
}
`
const AnimatedDialogContent = animated(DialogContent)
// destructure to not pass custom props to Dialog DOM element
const StyledDialogContent = styled(
// eslint-disable-next-line @typescript-eslint/no-unused-vars
({ margin, minHeight, maxHeight, maxWidth, mobile, isOpen, isLargeImageModal, tabIndex, zIndex, ...rest }) => (
)
).attrs({
'aria-label': 'dialog'
})>`
border: none;
height: ${({ mobile }) => (mobile ? '100%' : '100%')};
${upToExtraSmall`
height: 100%;
`}
&[data-reach-dialog-content] {
outline: none;
overflow: auto;
background-color: ${({ mainBackgroundColor = 'transparent' }) => mainBackgroundColor};
box-shadow: 0px 4px 8px 0px ${({ boxShadowColor = 'rgba(0,0,0,0.7)' }) => transparentize(0.95, boxShadowColor)};
display: flex;
align-self: center;
border-radius: 0;
margin: ${({ margin = '0 0 auto 0' }) => margin};
padding-top: 2rem;
width: ${({ isLargeImageModal }) => (isLargeImageModal ? '90' : '50')}vh;
max-width: ${({ maxHeight, maxWidth = '42rem', isLargeImageModal = false }) =>
`${isLargeImageModal ? maxHeight + 'vh' : maxWidth}`};
${({ maxHeight }) => maxHeight && `max-height: ${maxHeight};`}
${({ minHeight }) => minHeight && `min-height: ${minHeight};`}
}
`
export interface ModalProps {
isLargeImageModal?: boolean
isOpen: boolean
tabIndex?: 0 | -1
onDismiss: () => void
minHeight?: string
maxHeight?: string
maxWidth?: string
margin?: string
initialFocusRef?: React.RefObject
className?: string
children?: React.ReactNode
styleProps?: ModalStyleProps
}
export function Modal({
isOpen,
children,
className,
tabIndex,
onDismiss,
margin,
minHeight,
maxHeight = '90vh',
maxWidth,
styleProps = {},
initialFocusRef,
isLargeImageModal = false
}: ModalProps) {
const isMobile = useIsMobile()
useEffect(() => {
return () => {
onDismiss()
}
}, [onDismiss])
if (!isOpen) return null
return (
{/* prevents the automatic focusing of inputs on mobile by the reach dialog */}
{tabIndex === undefined || initialFocusRef || !isMobile ? null : }
{children}
)
}