mirror of
https://github.com/remvze/moodist.git
synced 2025-12-17 17:04:15 +00:00
89 lines
2.1 KiB
TypeScript
89 lines
2.1 KiB
TypeScript
import { useEffect } from 'react';
|
|
import { AnimatePresence, motion } from 'framer-motion';
|
|
import { IoClose } from 'react-icons/io5/index';
|
|
import FocusTrap from 'focus-trap-react';
|
|
|
|
import { Portal } from '@/components/portal';
|
|
|
|
import { fade, mix, slideY } from '@/lib/motion';
|
|
import { cn } from '@/helpers/styles';
|
|
|
|
import styles from './modal.module.css';
|
|
|
|
interface ModalProps {
|
|
children: React.ReactNode;
|
|
lockBody?: boolean;
|
|
onClose: () => void;
|
|
show: boolean;
|
|
wide?: boolean;
|
|
}
|
|
|
|
export function Modal({
|
|
children,
|
|
lockBody = true,
|
|
onClose,
|
|
show,
|
|
wide,
|
|
}: ModalProps) {
|
|
const variants = {
|
|
modal: mix(fade(), slideY(20)),
|
|
overlay: fade(),
|
|
};
|
|
|
|
useEffect(() => {
|
|
if (show && lockBody) {
|
|
document.body.style.overflow = 'hidden';
|
|
} else if (lockBody) {
|
|
document.body.style.overflow = 'auto';
|
|
}
|
|
}, [show, lockBody]);
|
|
|
|
useEffect(() => {
|
|
function keyListener(e) {
|
|
if (e.keyCode === 27) {
|
|
onClose();
|
|
}
|
|
}
|
|
|
|
document.addEventListener('keydown', keyListener);
|
|
|
|
return () => document.removeEventListener('keydown', keyListener);
|
|
});
|
|
|
|
return (
|
|
<Portal>
|
|
<AnimatePresence>
|
|
{show && (
|
|
<FocusTrap>
|
|
<div>
|
|
<motion.div
|
|
animate="show"
|
|
className={styles.overlay}
|
|
exit="hidden"
|
|
initial="hidden"
|
|
variants={variants.overlay}
|
|
onClick={onClose}
|
|
onKeyDown={onClose}
|
|
/>
|
|
<div className={styles.modal}>
|
|
<motion.div
|
|
animate="show"
|
|
className={cn(styles.content, wide && styles.wide)}
|
|
exit="hidden"
|
|
initial="hidden"
|
|
variants={variants.modal}
|
|
>
|
|
<button className={styles.close} onClick={onClose}>
|
|
<IoClose />
|
|
</button>
|
|
|
|
{children}
|
|
</motion.div>
|
|
</div>
|
|
</div>
|
|
</FocusTrap>
|
|
)}
|
|
</AnimatePresence>
|
|
</Portal>
|
|
);
|
|
}
|