From 4005b9c49d71e0eb0fbb80730a12c40b8b72523b Mon Sep 17 00:00:00 2001 From: Alicia Sykes Date: Fri, 7 Jul 2023 20:57:41 +0100 Subject: [PATCH] Creates a re-usable modal component --- src/components/Form/Modal.tsx | 86 +++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 src/components/Form/Modal.tsx diff --git a/src/components/Form/Modal.tsx b/src/components/Form/Modal.tsx new file mode 100644 index 0000000..8f9f29b --- /dev/null +++ b/src/components/Form/Modal.tsx @@ -0,0 +1,86 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import styled from 'styled-components'; +import colors from 'styles/colors'; +import Button from 'components/Form/Button'; + +interface ModalProps { + children: React.ReactNode; + isOpen: boolean; + closeModal: () => void; +} + +const Overlay = styled.div` + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + display: flex; + justify-content: center; + align-items: center; + background-color: rgba(0, 0, 0, 0.5); + animation: fadeIn 0.5s; + + @keyframes fadeIn { + 0% {opacity: 0;} + 100% {opacity: 1;} + } +`; + +const ModalWindow = styled.div` + width: 80%; + max-width: 500px; + background: ${colors.backgroundLighter}; + padding: 2rem; + border-radius: 12px; + box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1); + position: relative; + animation: appear 0.5s; + color: ${colors.textColor}; + box-shadow: 4px 4px 0px ${colors.bgShadowColor}; + @keyframes appear { + 0% {opacity: 0; transform: scale(0.9);} + 100% {opacity: 1; transform: scale(1);} + } +`; + +const Modal: React.FC = ({ children, isOpen, closeModal }) => { + const handleOverlayClick = (e: React.MouseEvent) => { + if (e.target === e.currentTarget) { + closeModal(); + } + }; + + const handleEscPress = (e: KeyboardEvent) => { + if (e.key === 'Escape') { + closeModal(); + } + }; + + React.useEffect(() => { + if (isOpen) { + window.addEventListener('keydown', handleEscPress); + } + + return () => { + window.removeEventListener('keydown', handleEscPress); + }; + }, [isOpen]); + + if (!isOpen) { + return null; + } + + return ReactDOM.createPortal( + + + {children} + + + , + document.body, + ); +}; + +export default Modal;