The final solution for WAI ARIA compatible Modal Dialogs or any full-screen tasks:
Now you could focus on a single task.
This is basically the inert
Minimal size - no more than 2kb, maximal - no more that 6kb. See sidecar example for details.
Example
Code sandbox example - https://codesandbox.io/s/p3vjp8mzw7
import {FocusOn} from 'react-focus-on';
<FocusOn
onClickOutside={callback}
onEscapeKey={callback}
shards={[externalRef]}
>
content you should be "focused" on
</FocusOn>
API
FocusOn
FocusOn
- the focus on component
enabled
- controls behaviour
[shards]
- a list of Refs to be considered as a part of the Lock. A way to properly handle portals or scattered lock.
[gapMode]
- the way removed ScrollBar would be compensated - margin(default), or padding. See scroll-locky documentation to find the one you need.
[noIsolation]
- disables aria-hidden isolation
[inert]
- enables pointer-events isolation (☠️ dangerous, use to disable "parent scrollbars", refer to react-remove-scroll documentation)
[allowPinchZoom]
- enables "pinch-n-zoom" behavior. By default it might be prevented, refer to react-remove-scroll documentation
[preventScrollOnFocus]
- prevents a side effect of a programatic page scroll caused by focusing elements. Especially useful to address modal animations.
[onActivation]
- on activation callback
[onDeactivation]
- on deactivation callback
[onClickOutside]
- on click outside of "focus" area. (actually on any event "outside")
[onEscapeKey]
- on Esc key down (and not defaultPrevented)
Additional API
Exposed from React-Focus-Lock
AutoFocusInside
- to mark autofocusable element
MoveFocusInside
- to move focus inside a component on mount
InFocusGuard
- to "guard" a shard node (place an invisible node before and after)
See react-focus-lock documentation for details.
Exposed from React-Remove-Scroll
classNames.fullWidth
- "100%" width (will not change on scrollbar removal)
classNames.zeroRight
- "0" right (will not change on scrollbar removal)
See react-remove-scroll for details.
PS: Version 1 used React-scroll-locky which was replaced by remove-scroll.
Size
- (🧩 full) 5.7kb after compression (excluding tslib).
- (👁 UI) 2kb, visual elements only
- (🚗 sidecar) 4kb, side effects
Import full
import {FocusOn} from 'react-focus-on';
<FocusOn>
{content}
</FocusOn>
Import UI only
import {FocusOn} from 'react-focus-on/UI';
import {sidecar} from "use-sidecar";
const FocusOnSidecar = sidecar(
() => import(/* webpackPrefetch: true */ "react-focus-on/sidecar")
);
<FocusOn
sideCar={FocusOnSidecar}
>
{content}
</FocusOn>
React versions
- v1 and v2 might work with React 15/16
- v3 require React 16.8+ (hooks)
Licence
MIT