Roving-tabindex controller for an ARIA tablist. Follows the W3C APG
Tabs pattern with automatic activation (arrow keys + Home/End
both move focus and activate the focused tab). Automatic activation
is appropriate here because panels are local React state with no
load latency; if a future tab ever has to lazy-fetch on activation
the call sites should switch to manual activation (Space/Enter to
activate after focus lands).
Held arrow keys traverse correctly: the hook reads the current
active id from a ref that's updated on every render, so successive
keydowns before React re-renders still see fresh state.
onChange does not need to be referentially stable — the hook
stashes the latest value in a ref so changing identities don't
thrash the tab button ref callbacks.
Roving-tabindex controller for an ARIA tablist. Follows the W3C APG Tabs pattern with automatic activation (arrow keys + Home/End both move focus and activate the focused tab). Automatic activation is appropriate here because panels are local React state with no load latency; if a future tab ever has to lazy-fetch on activation the call sites should switch to manual activation (Space/Enter to activate after focus lands).
Held arrow keys traverse correctly: the hook reads the current active id from a ref that's updated on every render, so successive keydowns before React re-renders still see fresh state.
onChangedoes not need to be referentially stable — the hook stashes the latest value in a ref so changing identities don't thrash the tab button ref callbacks.