# focus-trap-vue

> Vue component to trap the focus within a DOM element

Latest version **4.1.0** (published 2025-08-13) · MIT license · 0 weekly downloads

## Install

```sh
npm install focus-trap-vue
pnpm add focus-trap-vue
yarn add focus-trap-vue
bun add focus-trap-vue
```

## Health

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

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

Warnings: low downloads.

Negative: stale.

## Facts

| | |
|---|---|
| Version | 4.1.0 |
| Published | 2025-08-13 |
| First published | 2019-07-23 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 0 |
| Unpacked size | 39.3 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| GitHub stars | 216 |
| Author | Eduardo San Martin Morote |
| Maintainers | posva, dv8fromtheworld |
| Keywords | focus, trap, a11y, accessibility, modal, component, block, lock, vue |

## Links

- npm: https://www.npmjs.com/package/focus-trap-vue
- Repository: https://github.com/posva/focus-trap-vue
- Homepage: https://github.com/posva/focus-trap-vue#readme
- Issues: https://github.com/posva/focus-trap-vue/issues
- npm.io page: https://npm.io/package/focus-trap-vue

## Alternatives

- [@sveltejs/kit](https://npm.io/package/@sveltejs/kit.md) — 2.2M weekly downloads
- [@atlaskit/theme](https://npm.io/package/@atlaskit/theme.md) — 402.0K weekly downloads
- [@tangle-network/brand](https://npm.io/package/@tangle-network/brand.md) — 10.0K weekly downloads
- [seneca](https://npm.io/package/seneca.md) — 7.4K weekly downloads
- [@bsb/base](https://npm.io/package/@bsb/base.md) — 7.2K weekly downloads

## Recent versions

- 4.1.0 (latest) — 2025-08-13
- 3.3.1 (next) — 2022-06-28
- 1.1.1 (legacy) — 2021-01-11
- 4.0.3 — 2023-10-20
- 4.0.2 — 2023-02-26
- 4.0.1 — 2022-12-21
- 4.0.0 — 2022-12-15
- 3.4.0 — 2022-12-15
- 3.3.0 — 2022-05-11
- 3.2.1 — 2021-07-07
- 3.2.0 — 2021-06-03
- 3.1.0 — 2020-10-22
- 1.1.0 — 2020-10-22
- 3.0.2 — 2020-09-23
- 3.0.1 — 2020-09-18
- … 11 more at https://npm.io/package/focus-trap-vue/versions

## README

# focus-trap-vue [![Build Status](https://badgen.net/circleci/github/posva/focus-trap-vue)](https://circleci.com/gh/posva/focus-trap-vue) [![npm package](https://badgen.net/npm/v/focus-trap-vue)](https://www.npmjs.com/package/focus-trap-vue) [![thanks](https://badgen.net/badge/thanks/♥/pink)](https://github.com/posva/thanks)

> Vue component to trap the focus within a DOM element

## Installation

### For Vue 2

```sh
npm install focus-trap focus-trap-vue@legacy
```

###  For Vue 3

```sh
npm install focus-trap focus-trap-vue
```

## Usage

This library exports one single named export `FocusTrap` and **requires
[`focus-trap`](https://github.com/focus-trap/focus-trap) as a peer
dependency**. So you can locally import the component or declare it globally:

###  Register globally in a Vue 2 app

```js
import { FocusTrap } from 'focus-trap-vue'

Vue.component('FocusTrap', FocusTrap)
```

###  Register globally in a Vue 3 app

```js
import { FocusTrap } from 'focus-trap-vue'

createApp(App)
  .component('FocusTrap', FocusTrap)
  .mount('#app')
```

**Note this documentation is for Vue 3 and some props/events might not exist in the Vue 2 version**

`FocusTrap` can be controlled in three different ways:

- by using the `active` _Boolean_ prop
- by using `v-model:active` (uses the `active` prop, _Vue 3 only_)
- by calling the `activate`/`deactivate` method on the component

The recommended approach is using `v-model:active` and it should contain **one single child**:

```html
<focus-trap v-model:active="isActive">
  <modal-dialog tabindex="-1">
    <p>Do you accept the cookies?</p>
    <button @click="acceptCookies">Yes</button>
    <button @click="isActive = false">No</button>
  </modal-dialog>
</focus-trap>
```

When `isActive` becomes `true`, it activates the focus trap. By default it sets
the focus to its child, so make sure the element is a focusable element. If it's
not you wil need to give it the `tabindex="-1"` attribute. You can also
customize the initial element focused. This element should be an element that
the user can interact with. For example, an input. It's a good practice to
always focus an interactable element instead of the modal container:

```html
<focus-trap v-model:active="isActive" :initial-focus="() => $refs.nameInput">
  <modal-dialog>
    <p>What name do you want to use?</p>
    <form @submit.prevent="setName">
      <label>
        New Name
        <input ref="nameInput" />
      </label>
      <button>Change name</button>
    </form>
  </modal-dialog>
</focus-trap>
```

### Props

`FocusTrap` also accepts other props:

- `escapeDeactivates`: `boolean`
- `returnFocusOnDeactivate`: `boolean`
- `allowOutsideClick`: `boolean | ((e: MouseEvent | TouchEvent) => boolean)`
- `clickOutsideDeactivates`: `boolean | ((e: MouseEvent | TouchEvent) => boolean)`
- `initialFocus`: `string | (() => Element)` _Selector or function returning an Element_
- `fallbackFocus`: `string | (() => Element)` _Selector or function returning an Element_
- `delayInitialFocus`: `boolean`
- `tabbableOptions`: `FocusTrapTabbableOptions` _Options passed to `tabbableOptions`_

Please, refer to
[focus-trap](https://github.com/focus-trap/focus-trap#focustrap--createfocustrapelement-createoptions)
documentation to know what they do.

### Events

`FocusTrap` emits 2 events. They are in-sync with the prop `active`

- `activate`: Whenever the trap activates
- `deactivate`: Whenever the trap deactivates (note it can also be deactivated by
  pressing <kbd>Esc</kbd> or clicking outside)

### Methods

`FocusTrap` can be used without `v-model:active`. In that case, you will use the
methods and _probably_ need to initialize the trap as _deactivated_, otherwise,
the focus will start as active:

```html
<button @click="() => $refs.focusTrap.activate()">Show the modal</button>

<focus-trap :active="false" ref="focusTrap">
  <modal-dialog>
    <p>Hello there!</p>
    <button @click="() => $refs.focusTrap.deactivate()">Okay...</button>
  </modal-dialog>
</focus-trap>
```

Note the use of arrow functions, this is necessary because we are accessing
`$refs` which are unset on first render.

## Related

- Focus Trap: https://github.com/focus-trap/focus-trap

## License

[MIT](http://opensource.org/licenses/MIT)

<div align="right">
<sub><em>
This project was created using the <a href="https://github.com/posva/focus-trap-vue-boilerplate" rel="nofollow">Vue Library boilerplate</a> by <a href="https://github.com/posva" rel="nofollow">posva</a>
</em></sub>
</div>

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