fix: prevent focus loss by using ref for onClose in Modal component
Build & Push Docker Image / build (push) Successful in 4m6s
Build & Push Docker Image / build (release) Successful in 4m12s

This commit is contained in:
2026-06-03 10:40:38 +02:00
parent 10f0ffd2e5
commit fbbcd79719
+9 -2
View File
@@ -8,10 +8,17 @@ export default function Modal({ title, children, onClose, maxWidth = 'max-w-lg'
const dialogRef = useRef(null); const dialogRef = useRef(null);
const previouslyFocused = useRef(null); const previouslyFocused = useRef(null);
// Keep the latest onClose in a ref so the mount-only effect below can call it
// without listing onClose as a dependency. Callers pass a fresh inline arrow
// each render; depending on it would re-run the effect on every keystroke and
// steal focus back to the dialog (kicking the user out of input fields).
const onCloseRef = useRef(onClose);
onCloseRef.current = onClose;
useEffect(() => { useEffect(() => {
previouslyFocused.current = document.activeElement; previouslyFocused.current = document.activeElement;
const handleKey = (e) => { const handleKey = (e) => {
if (e.key === 'Escape') onClose?.(); if (e.key === 'Escape') onCloseRef.current?.();
}; };
document.addEventListener('keydown', handleKey); document.addEventListener('keydown', handleKey);
// Focus the dialog so screen readers announce it and keyboard focus lands inside // Focus the dialog so screen readers announce it and keyboard focus lands inside
@@ -20,7 +27,7 @@ export default function Modal({ title, children, onClose, maxWidth = 'max-w-lg'
document.removeEventListener('keydown', handleKey); document.removeEventListener('keydown', handleKey);
previouslyFocused.current?.focus?.(); previouslyFocused.current?.focus?.();
}; };
}, [onClose]); }, []);
return ( return (
<div className="fixed inset-0 z-50 flex items-center justify-center p-4"> <div className="fixed inset-0 z-50 flex items-center justify-center p-4">