Roving Focus Provider
sh0ji opened this issue · 1 comments
sh0ji commented
Now that we have a structure in place for exposing React context providers, I'd like to ship a roving focus provider. Wrapping a section of your code in this should cause that section to keep track of the current roving focus index, making it accessible via a hook so that you can do something like this:
const MyListbox = ({ items, onSelect, selected }) => {
const [focusIndex, setFocusIndex] = useRovingFocus();
return items.map((item, i) => (
<li
role="option"
aria-selected={selected.includes(item)}
tabIndex={(focusIndex === i) ? 0 : -1}
onKeyDown={(e) => {
if (e.key === 'Enter' && onSelect) {
onSelect(item);
}
}}
onClick={(e) => {
e.target.focus();
setFocusIndex(i);
}}
ref={(el) => {
if (el && focusIndex === i) el.focus();
}}
>
{ item }
</li>
));
};
sh0ji commented
This was implemented as a hook instead of a provider in #136: https://github.com/wwnorton/design-system/blob/main/packages/react/src/utilities/rovingTabindex.
While I did explore using a <RovingTabindexProvider>
, all of the scenarios where it would be used also had the mapped children in context so it felt redundant and better designed with a hook.