/** * @file Dialog component */ import React, { useEffect, useRef } from "react"; import styles from "./Dialog.module.css"; export type DialogProps = { isOpen: boolean; onClose: () => void; title?: string; children: React.ReactNode; size?: "small" | "medium" | "large" | "fullscreen"; showCloseButton?: boolean; closeOnOverlayClick?: boolean; closeOnEscape?: boolean; className?: string; }; export const Dialog: React.FC = ({ isOpen, onClose, title, children, size = "medium", showCloseButton = true, closeOnOverlayClick = true, closeOnEscape = true, className = "", }) => { const dialogRef = useRef(null); const previousFocusRef = useRef(null); useEffect(() => { if (isOpen) { previousFocusRef.current = document.activeElement as HTMLElement; dialogRef.current?.focus(); } else if (previousFocusRef.current) { previousFocusRef.current.focus(); } }, [isOpen]); useEffect(() => { const handleEscape = (event: KeyboardEvent) => { if (closeOnEscape && event.key === "Escape") { onClose(); } }; if (isOpen) { document.addEventListener("keydown", handleEscape); document.body.style.overflow = "hidden"; } return () => { document.removeEventListener("keydown", handleEscape); document.body.style.overflow = ""; }; }, [isOpen, closeOnEscape, onClose]); const handleOverlayClick = (event: React.MouseEvent) => { if (closeOnOverlayClick && event.target === event.currentTarget) { onClose(); } }; if (!isOpen) { return null; } const dialogClasses = [styles.dialog, className].filter(Boolean).join(" "); return (
{(title || showCloseButton) && (
{title && (

{title}

)} {showCloseButton && ( )}
)}
{children}
); };