fix(feed): clamp the view menu's roving index to the option list
Guards the shared switcher against a caller whose option list shrinks while the menu is open, which would leave every item un-tabbable.
This commit is contained in:
@@ -54,9 +54,12 @@ export default function ViewSwitcher<T extends string>({
|
|||||||
setFocusIdx(currentIdx);
|
setFocusIdx(currentIdx);
|
||||||
setOpen(true);
|
setOpen(true);
|
||||||
}
|
}
|
||||||
|
// Clamped at render, so a caller whose option list shrinks while the menu is open can't leave
|
||||||
|
// the roving tabindex pointing past the end (which would make every item un-tabbable).
|
||||||
|
const rovingIdx = Math.min(focusIdx, options.length - 1);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (open) itemRefs.current[focusIdx]?.focus();
|
if (open) itemRefs.current[rovingIdx]?.focus();
|
||||||
}, [open, focusIdx]);
|
}, [open, rovingIdx]);
|
||||||
|
|
||||||
const current = options[currentIdx];
|
const current = options[currentIdx];
|
||||||
if (!current) return null;
|
if (!current) return null;
|
||||||
@@ -122,7 +125,7 @@ export default function ViewSwitcher<T extends string>({
|
|||||||
}}
|
}}
|
||||||
role="menuitemradio"
|
role="menuitemradio"
|
||||||
aria-checked={on}
|
aria-checked={on}
|
||||||
tabIndex={i === focusIdx ? 0 : -1}
|
tabIndex={i === rovingIdx ? 0 : -1}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
onChange(o.id);
|
onChange(o.id);
|
||||||
close();
|
close();
|
||||||
|
|||||||
Reference in New Issue
Block a user