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:
2026-07-16 02:44:22 +02:00
parent 67f14d145f
commit 1a94411a03
+6 -3
View File
@@ -54,9 +54,12 @@ export default function ViewSwitcher<T extends string>({
setFocusIdx(currentIdx);
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(() => {
if (open) itemRefs.current[focusIdx]?.focus();
}, [open, focusIdx]);
if (open) itemRefs.current[rovingIdx]?.focus();
}, [open, rovingIdx]);
const current = options[currentIdx];
if (!current) return null;
@@ -122,7 +125,7 @@ export default function ViewSwitcher<T extends string>({
}}
role="menuitemradio"
aria-checked={on}
tabIndex={i === focusIdx ? 0 : -1}
tabIndex={i === rovingIdx ? 0 : -1}
onClick={() => {
onChange(o.id);
close();