import React from 'react'; import styled from '@emotion/styled'; import { motion } from 'framer-motion'; const StyledModalDiv = styled(motion.div)<{ size?: ModalSize; padding?: ModalPadding; }>` display: flex; flex-direction: column; background: ${({ theme }) => theme.background.primary}; color: ${({ theme }) => theme.font.color.primary}; border-radius: ${({ theme }) => theme.border.radius.md}; overflow: hidden; max-height: 90vh; z-index: 10000; // should be higher than Backdrop's z-index width: ${({ size, theme }) => { switch (size) { case 'small': return theme.modal.size.sm; case 'medium': return theme.modal.size.md; case 'large': return theme.modal.size.lg; default: return 'auto'; } }}; padding: ${({ padding, theme }) => { switch (padding) { case 'none': return theme.spacing(0); case 'small': return theme.spacing(2); case 'medium': return theme.spacing(4); case 'large': return theme.spacing(6); default: return 'auto'; } }}; `; const StyledHeader = styled.div` align-items: center; display: flex; flex-direction: row; height: 60px; overflow: hidden; padding: ${({ theme }) => theme.spacing(5)}; `; const StyledContent = styled.div` display: flex; flex: 1; flex: 1 1 0%; flex-direction: column; overflow-y: auto; padding: ${({ theme }) => theme.spacing(10)}; `; const StyledFooter = styled.div` align-items: center; display: flex; flex-direction: row; height: 60px; overflow: hidden; padding: ${({ theme }) => theme.spacing(5)}; `; const StyledBackDrop = styled(motion.div)` align-items: center; background: ${({ theme }) => theme.background.overlay}; display: flex; height: 100%; justify-content: center; left: 0; position: fixed; top: 0; width: 100%; z-index: 9999; `; /** * Modal components */ type ModalLayoutHeaderProps = React.PropsWithChildren & { className?: string; }; const ModalLayoutHeader = ({ children, className }: ModalLayoutHeaderProps) => ( {children} ); type ModalLayoutContentProps = React.PropsWithChildren & { className?: string; }; const ModalLayoutContent = ({ children, className, }: ModalLayoutContentProps) => ( {children} ); type ModalLayoutFooterProps = React.PropsWithChildren & { className?: string; }; const ModalLayoutFooter = ({ children, className }: ModalLayoutFooterProps) => ( {children} ); /** * Modal */ export type ModalSize = 'small' | 'medium' | 'large'; export type ModalPadding = 'none' | 'small' | 'medium' | 'large'; export type ModalLayoutProps = React.PropsWithChildren & { size?: ModalSize; padding?: ModalPadding; className?: string; modalRef?: React.RefObject; }; const modalVariants = { hidden: { opacity: 0 }, visible: { opacity: 1 }, exit: { opacity: 0 }, }; // This component should be used over Modal when seeking a modal feel without modal state (hotkeyScope etc) export const ModalLayout = ({ children, size = 'medium', padding = 'medium', modalRef, className, }: ModalLayoutProps) => { return ( {children} ); }; ModalLayout.Header = ModalLayoutHeader; ModalLayout.Content = ModalLayoutContent; ModalLayout.Footer = ModalLayoutFooter;