fix: prevent focus loss by using ref for onClose in Modal component
This commit is contained in:
@@ -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">
|
||||||
|
|||||||
Reference in New Issue
Block a user