fix(web): keep focus in modals while typing (add-artist bug)
The Modal focus-trap effect depended on [open, onClose] and called panelRef.focus() on every run. Callers that pass a fresh onClose each render (the common case, e.g. artists-client's closeAdd) re-ran the effect on every parent re-render — so typing one char into the add-artist search (setQuery → re-render → new onClose) yanked focus off the <input> back onto the panel, making the field untypable. Hold the latest onClose in a ref and depend on [open] alone, so focus-on-open runs once per open. Fixes every Modal caller, not just add-artist. Verified live via Playwright: typing "radiohead" one key at a time keeps the value and document.activeElement on the search input. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -22,6 +22,12 @@ export function Modal({
|
|||||||
}) {
|
}) {
|
||||||
const panelRef = useRef<HTMLDivElement>(null);
|
const panelRef = useRef<HTMLDivElement>(null);
|
||||||
const lastFocus = useRef<HTMLElement | null>(null);
|
const lastFocus = useRef<HTMLElement | null>(null);
|
||||||
|
// Keep the latest onClose in a ref so the setup effect can depend on [open] alone. If it
|
||||||
|
// depended on onClose, a caller passing a fresh callback each render (the common case)
|
||||||
|
// would re-run the effect on every parent re-render — and panelRef.focus() below would
|
||||||
|
// yank focus off a just-typed <input> back onto the panel (the add-artist modal bug).
|
||||||
|
const onCloseRef = useRef(onClose);
|
||||||
|
onCloseRef.current = onClose;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!open) return;
|
if (!open) return;
|
||||||
@@ -32,7 +38,7 @@ export function Modal({
|
|||||||
|
|
||||||
function onKey(e: KeyboardEvent) {
|
function onKey(e: KeyboardEvent) {
|
||||||
if (e.key === "Escape") {
|
if (e.key === "Escape") {
|
||||||
onClose();
|
onCloseRef.current();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (e.key !== "Tab") return;
|
if (e.key !== "Tab") return;
|
||||||
@@ -54,7 +60,7 @@ export function Modal({
|
|||||||
document.body.style.overflow = prevOverflow;
|
document.body.style.overflow = prevOverflow;
|
||||||
lastFocus.current?.focus();
|
lastFocus.current?.focus();
|
||||||
};
|
};
|
||||||
}, [open, onClose]);
|
}, [open]);
|
||||||
|
|
||||||
if (!open || typeof document === "undefined") return null;
|
if (!open || typeof document === "undefined") return null;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user