diff --git a/src/components/Modal.tsx b/src/components/Modal.tsx index b6dd634..086a8d3 100644 --- a/src/components/Modal.tsx +++ b/src/components/Modal.tsx @@ -1,4 +1,4 @@ -import React, { useEffect } from "react"; +import React, { useEffect, useRef } from "react"; import { X } from "lucide-react"; import { Card } from "./ui/card"; import { Button } from "./ui/button"; @@ -23,16 +23,44 @@ export const Modal: React.FC = ({ footer, maxWidth = "max-w-lg", }) => { - useEffect(() => { - if (isOpen) { - document.body.style.overflow = "hidden"; - } else { - document.body.style.overflow = "unset"; - } - return () => { - document.body.style.overflow = "unset"; - }; - }, [isOpen]); + const cardRef = useRef(null); + + useEffect(() => { + const handleKeyDown = (event: KeyboardEvent) => { + if (event.key === "Escape") { + onClose(); + } + }; + + if (isOpen) { + document.body.style.overflow = "hidden"; + document.addEventListener("keydown", handleKeyDown); + } else { + document.body.style.overflow = "unset"; + } + return () => { + document.body.style.overflow = "unset"; + document.removeEventListener("keydown", handleKeyDown); + }; + }, [isOpen, onClose]); + + useEffect(() => { + if (!isOpen) return; + + const focusTimer = window.setTimeout(() => { + const activeElement = document.activeElement; + if (activeElement instanceof HTMLElement && cardRef.current?.contains(activeElement)) { + return; + } + + const firstTextInput = cardRef.current?.querySelector( + 'input:not([type]), input[type="text"], input[type="search"], input[type="email"], input[type="tel"], input[type="password"], input[type="number"], textarea', + ); + firstTextInput?.focus(); + }, 0); + + return () => window.clearTimeout(focusTimer); + }, [isOpen]); if (!isOpen) return null; @@ -42,6 +70,7 @@ export const Modal: React.FC = ({ onClick={onClose} > e.stopPropagation()} >