UNPKG

react-tabindex

Version:

Sanely manage <kbd>Tab</kbd> accessibility in React with `<Untabbable>` and the `useTabIndex` hook!

47 lines (40 loc) 1.9 kB
import React, { useContext } from 'react'; var UntabbableContext = React.createContext(false); /** * A wrapper that marks a section of the component tree as unreachable via the * <kbd>Tab</kbd> key. It renders no element on its own and must contain a * single element child. By itself it does nothing, but descendants using the * `useTabIndex` hook will receive `-1` if there is an active Untabbable * ancestor. * * If you need to toggle tabbability back on, set the `active` prop to false. * This is preferable to conditionally inserting the Untabbable parent since it * keeps the component tree structure the same, avoiding remounts. */ function Untabbable({ // Whether this Untabbable is actually active, overriding the output of // `useTabIndex`. active = true, // Context provider children. children, // Whether this Untabbable should ignore ancestor Untabbable state. This is // rarely what you want, unless you are setting up something with modal // elements. In that case, you may want all elements behind the modal to // become untabbable, but the modal element is likely to have that same // Untabbable context as its ancestor (since context is preserved across // portals). Thus, the content of the modal component itself should be wrapped // in an Untabbable with the `reset` prop. reset = false }) { const anyParentActive = useContext(UntabbableContext); // Explicitly force value to Boolean, since users often rely on truthiness // shorthand like `active={object}`, `active={array.length}`, etc. const value = Boolean(reset ? active : active || anyParentActive); return React.createElement(UntabbableContext.Provider, { value: value }, children); } function useTabIndex(tabIndex) { const isUntabbable = useContext(UntabbableContext); return isUntabbable ? -1 : tabIndex; } export { Untabbable, UntabbableContext, useTabIndex };