Skip to content

Instantly share code, notes, and snippets.

@nicolasleal570
Last active March 25, 2021 21:09
Show Gist options
  • Save nicolasleal570/2c994fec87fd360d4da0d5a6a2b31742 to your computer and use it in GitHub Desktop.
Save nicolasleal570/2c994fec87fd360d4da0d5a6a2b31742 to your computer and use it in GitHub Desktop.
Modal Component
import React from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import useOutsideClick from '../../hooks/useOutsideClick';
interface ModalProps {
children?: React.ReactNode;
isOpen: boolean;
setOpen: React.Dispatch<React.SetStateAction<boolean>>;
}
const modalVariant = {
initial: { opacity: 0 },
isOpen: { opacity: 1 },
exit: { opacity: 0 },
};
const containerVariant = {
initial: { top: '-50%', transition: { type: 'spring' } },
isOpen: { top: '50%' },
exit: { top: '-50%' },
};
export default function Modal({
children,
isOpen = false,
setOpen,
}: ModalProps) {
const ref = React.useRef(null);
React.useEffect(() => {
if (isOpen) {
document.body.style.paddingRight = "15px";
document.body.style.overflow = "hidden";
} else {
document.body.style.paddingRight = "";
document.body.style.overflow = "";
}
return () => {
document.body.style.paddingRight = "";
document.body.style.overflow = "";
};
}, [isOpen]);
const handleClickOutside = () => {
setOpen(false);
};
useOutsideClick(ref, handleClickOutside);
return (
<AnimatePresence>
{isOpen ? (
<motion.section
ref={ref}
id="overlay"
className="Modal"
initial="initial"
animate="isOpen"
exit="exit"
variants={modalVariant}
>
<motion.div
className="content-container"
variants={containerVariant}
role="dialog"
aria-modal="true"
aria-labelledby="modal-headline"
id="modal"
>
{children}
</motion.div>
</motion.section>
) : null}
</AnimatePresence>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment