7 changed files with 237 additions and 224 deletions
@ -1,58 +1,74 @@ |
|||||
import type React from 'react'; |
import type React from 'react'; |
||||
|
|
||||
import { m } from 'framer-motion'; |
import { AnimatePresence, m } from 'framer-motion'; |
||||
import { FiX } from 'react-icons/fi'; |
import { FiX } from 'react-icons/fi'; |
||||
|
|
||||
import { useAppSelector } from '@hooks/useAppSelector'; |
import { useAppSelector } from '@hooks/useAppSelector'; |
||||
|
|
||||
import { IconButton } from './button/IconButton'; |
import { IconButton } from './button/IconButton'; |
||||
import { Card } from './Card'; |
import { Card, CardProps } from './Card'; |
||||
|
|
||||
export interface ModalProps { |
export interface ModalProps extends CardProps { |
||||
title: string; |
open: boolean; |
||||
|
bgDismiss?: boolean; |
||||
onClose: () => void; |
onClose: () => void; |
||||
actions?: React.ReactNode; |
|
||||
children: React.ReactNode; |
|
||||
} |
} |
||||
|
|
||||
export const Modal = ({ |
export const Modal = ({ |
||||
title, |
open, |
||||
|
bgDismiss, |
||||
onClose, |
onClose, |
||||
actions, |
actions, |
||||
children, |
...props |
||||
}: ModalProps): JSX.Element => { |
}: ModalProps): JSX.Element => { |
||||
const darkMode = useAppSelector((state) => state.app.darkMode); |
const darkMode = useAppSelector((state) => state.app.darkMode); |
||||
|
|
||||
return ( |
return ( |
||||
<m.div className={`fixed inset-0 z-30 ${darkMode ? 'dark' : ''}`}> |
<AnimatePresence> |
||||
<m.div |
{open && ( |
||||
className="fixed h-full w-full backdrop-blur-sm backdrop-filter" |
<m.div |
||||
onClick={onClose} |
className={`fixed inset-0 ${darkMode ? 'dark' : ''} ${ |
||||
/> |
open ? 'z-30' : 'z-0' |
||||
<m.div className="text-center "> |
}`}
|
||||
<span |
|
||||
className="inline-block h-screen align-middle " |
|
||||
aria-hidden="true" |
|
||||
> |
> |
||||
​ |
<m.div |
||||
</span> |
initial={{ opacity: 0 }} |
||||
<div className="inline-block w-full max-w-3xl align-middle"> |
animate={{ opacity: 1 }} |
||||
<Card |
exit={{ opacity: 0 }} |
||||
border |
transition={{ duration: 0.1 }} |
||||
draggable |
className="fixed h-full w-full backdrop-blur-md backdrop-filter" |
||||
title={title} |
onClick={(): void => { |
||||
actions={ |
bgDismiss && onClose(); |
||||
<> |
}} |
||||
{actions} |
/> |
||||
<IconButton tooltip="Close" icon={<FiX />} onClick={onClose} /> |
<m.div className="text-center "> |
||||
</> |
<span |
||||
} |
className="inline-block h-screen align-middle " |
||||
className="relative flex-col gap-4 " |
aria-hidden="true" |
||||
> |
> |
||||
{children} |
​ |
||||
</Card> |
</span> |
||||
</div> |
<div className="inline-block w-full max-w-3xl align-middle"> |
||||
</m.div> |
<Card |
||||
</m.div> |
border |
||||
|
draggable |
||||
|
actions={ |
||||
|
<div className="flex gap-2"> |
||||
|
{actions} |
||||
|
<IconButton |
||||
|
tooltip="Close" |
||||
|
icon={<FiX />} |
||||
|
onClick={onClose} |
||||
|
/> |
||||
|
</div> |
||||
|
} |
||||
|
className="relative flex-col gap-4" |
||||
|
{...props} |
||||
|
/> |
||||
|
</div> |
||||
|
</m.div> |
||||
|
</m.div> |
||||
|
)} |
||||
|
</AnimatePresence> |
||||
); |
); |
||||
}; |
}; |
||||
|
|||||
Loading…
Reference in new issue