# react-focus-on

> The final solution for WAI ARIA compatible modal dialogs or full-screen tasks.

Latest version **3.10.2** (published 2025-12-22) · MIT license · 0 weekly downloads

## Install

```sh
npm install react-focus-on
pnpm add react-focus-on
yarn add react-focus-on
bun add react-focus-on
```

## Health

**Score 60/100 (C)** — status: stable.

Positive: has types; esm support; no vulnerabilities; high quality score.

Warnings: low downloads.

## Facts

| | |
|---|---|
| Version | 3.10.2 |
| Published | 2025-12-22 |
| First published | 2018-01-15 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Node | >=8.5.0 |
| Dependencies | 6 |
| Unpacked size | 57.9 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 351 |
| Author | Anton Korzunov |
| Maintainers | kashey |
| Keywords | react, modal, focus-management, scroll, isolation |

## Links

- npm: https://www.npmjs.com/package/react-focus-on
- Repository: https://github.com/theKashey/react-focus-on
- Homepage: https://github.com/theKashey/react-focus-on#readme
- Issues: https://github.com/theKashey/react-focus-on/issues
- npm.io page: https://npm.io/package/react-focus-on

## Dependencies (6)

- [tslib](https://npm.io/package/tslib.md) ^2.3.1
- [aria-hidden](https://npm.io/package/aria-hidden.md) ^1.2.5
- [use-sidecar](https://npm.io/package/use-sidecar.md) ^1.1.3
- [react-focus-lock](https://npm.io/package/react-focus-lock.md) ^2.13.7
- [react-remove-scroll](https://npm.io/package/react-remove-scroll.md) ^2.6.4
- [react-style-singleton](https://npm.io/package/react-style-singleton.md) ^2.2.3

## Alternatives

- [mobx-react](https://npm.io/package/mobx-react.md) — 2.8M weekly downloads
- [rc-tree](https://npm.io/package/rc-tree.md) — 2.6M weekly downloads
- [@react-oauth/google](https://npm.io/package/@react-oauth/google.md) — 1.3M weekly downloads
- [@wagmi/connectors](https://npm.io/package/@wagmi/connectors.md) — 877.0K weekly downloads
- [vee-validate](https://npm.io/package/vee-validate.md) — 836.4K weekly downloads

## Recent versions

- 3.10.2 (latest) — 2025-12-22
- 3.1.1 (beta) — 2019-09-21
- 3.10.1 — 2025-11-30
- 3.10.0 — 2025-05-18
- 3.9.4 — 2024-09-11
- 3.9.3 — 2024-04-13
- 3.9.2 — 2024-03-03
- 3.9.1 — 2023-07-09
- 3.9.0 — 2023-07-05
- 3.8.2 — 2023-06-25
- 3.8.1 — 2023-04-30
- 3.8.0 — 2023-03-16
- 3.7.0 — 2022-11-13
- 3.6.0 — 2022-05-01
- 3.5.4 — 2021-11-09
- … 32 more at https://npm.io/package/react-focus-on/versions

## README

<div align="center">
  <h1>👁 React-Focus-On </h1>
  <br/>
   lock and loaded!
  <br/>
  
  <a href="https://www.npmjs.com/package/react-focus-on">
    <img src="https://img.shields.io/npm/v/react-focus-on.svg?style=flat-square" />
  </a>
    
  <a href="https://travis-ci.org/theKashey/react-focus-on">
   <img src="https://img.shields.io/travis/theKashey/react-focus-on.svg?style=flat-square" alt="Build status">
  </a> 

  <a href="https://www.npmjs.com/package/react-focus-on">
   <img src="https://img.shields.io/npm/dm/react-focus-on.svg" alt="npm downloads">
  </a> 

  <a href="https://bundlephobia.com/result?p=react-focus-on">
   <img src="https://img.shields.io/bundlephobia/minzip/react-focus-on.svg" alt="bundle size">
  </a>   
  <br/>
</div>

The final solution for WAI ARIA compatible Modal Dialogs or any full-screen tasks:
- locks __focus__ inside using [react-focus-lock](https://github.com/theKashey/react-focus-lock)
- disables page __scroll__ and user interactions using [react-remove-scroll](https://github.com/theKashey/react-remove-scroll)
- hides rest of a page from screen-readers using [aria-hidden](https://github.com/theKashey/aria-hidden)

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
```js
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.
--- 
 - `[autoFocus=true]` - enables or disables `auto focus` management (see [react-focus-lock documentation](https://github.com/theKashey/react-focus-lock))
 - `[returnFocus=true]` - enables or disables `return focus` on lock deactivation (see [react-focus-lock documentation](https://github.com/theKashey/react-focus-lock))
 - `[whiteList=fn]` - you could whitelist locations FocusLock should carry about. Everything outside it will ignore. For example - any modals (see [react-focus-lock documentation](https://github.com/theKashey/react-focus-lock))
 - `[crossFrame=true]` - enables or disables cross frame focus trapping. Setting this to false allows focus to move outside iframes (see [react-focus-lock issue](https://github.com/theKashey/react-focus-lock/issues/104))
---
 - `[gapMode]` - the way removed ScrollBar would be _compensated_ - margin(default), or padding. See [scroll-locky documentation](https://github.com/theKashey/react-scroll-locky#gap-modes) 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](https://github.com/theKashey/react-remove-scroll) documentation)
 - `[allowPinchZoom]` - enables "pinch-n-zoom" behavior. By default it might be prevented, refer to [react-remove-scroll](https://github.com/theKashey/react-remove-scroll) documentation
 - `[preventScrollOnFocus]` - prevents a [side effect of a programatic page scroll](https://github.com/theKashey/react-focus-on/issues/62) 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](https://github.com/theKashey/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](https://github.com/theKashey/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
```js
import {FocusOn} from 'react-focus-on';

<FocusOn>
 {content}
</FocusOn> 
```  

### Import UI only
```js
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

---
_Source: https://npm.io/package/react-focus-on · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
