fix(modal): add keyboard close and autofocus

This commit is contained in:
2026-06-07 15:36:43 +03:30
parent 8abfcc9c2b
commit 132c8c44ef

View File

@@ -1,4 +1,4 @@
import React, { useEffect } from "react"; import React, { useEffect, useRef } from "react";
import { X } from "lucide-react"; import { X } from "lucide-react";
import { Card } from "./ui/card"; import { Card } from "./ui/card";
import { Button } from "./ui/button"; import { Button } from "./ui/button";
@@ -23,16 +23,44 @@ export const Modal: React.FC<ModalProps> = ({
footer, footer,
maxWidth = "max-w-lg", maxWidth = "max-w-lg",
}) => { }) => {
useEffect(() => { const cardRef = useRef<HTMLDivElement>(null);
if (isOpen) {
document.body.style.overflow = "hidden"; useEffect(() => {
} else { const handleKeyDown = (event: KeyboardEvent) => {
document.body.style.overflow = "unset"; if (event.key === "Escape") {
} onClose();
return () => { }
document.body.style.overflow = "unset"; };
};
}, [isOpen]); 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<HTMLElement>(
'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; if (!isOpen) return null;
@@ -42,6 +70,7 @@ export const Modal: React.FC<ModalProps> = ({
onClick={onClose} onClick={onClose}
> >
<Card <Card
ref={cardRef}
className={`flex max-h-[calc(100vh-2rem)] w-full flex-col ${maxWidth} bg-white dark:bg-slate-900 text-slate-900 dark:text-slate-100 border-0 shadow-xl overflow-hidden rounded-2xl`} className={`flex max-h-[calc(100vh-2rem)] w-full flex-col ${maxWidth} bg-white dark:bg-slate-900 text-slate-900 dark:text-slate-100 border-0 shadow-xl overflow-hidden rounded-2xl`}
onClick={(e) => e.stopPropagation()} onClick={(e) => e.stopPropagation()}
> >