Package detail

focus-trap-vue

posva192.6kMIT4.0.3

Vue component to trap the focus within a DOM element

focus, trap, a11y, accessibility

readme

focus-trap-vue Build Status npm package thanks

Vue component to trap the focus within a DOM element

Installation

For Vue 2

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

For Vue 3

npm install focus-trap focus-trap-vue

Usage

This library exports one single named export FocusTrap and requires focus-trap as a peer dependency. So you can locally import the component or declare it globally:

Register globally in a Vue 2 app

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

Vue.component('FocusTrap', FocusTrap)

Register globally in a Vue 3 app

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:

<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:

<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 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:

<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

License

MIT

This project was created using the Vue Library boilerplate by posva

changelog

4.0.3 (2023-10-20)

Bug Fixes

  • preventScroll property through to createFocusTrap. (#507) (e04a40d)

4.0.2 (2023-02-26)

Bug Fixes

  • forward delayInitialFocus prop to createFocusTrap (#454) (f067ea6)

4.0.1 (2022-12-21)

Bug Fixes

4.0.0 (2022-12-15)

Code Refactoring

  • upgrade focus-trap to v7 (445b128)

BREAKING CHANGES

3.4.0 (2022-12-15)

Features

3.3.1 (2022-06-28)

Features

  • Allow passing a function to clickOutsideDeactivates prop (#407) (a4ab6bc)

3.3.0 (2022-05-11)

Bug Fixes

Features

3.2.1 (2021-07-07)

Bug Fixes

  • Fixed compatibility problems introduced for Vue2 Migrations (ace36a0)
  • Re-exposed the activate/deactivate methods on component (#375) (f5480ac)

Features

3.2.0 (2021-06-03)

Upgrade all dependencies

Features

3.1.0 (2020-10-22)

Features

  • backport support of clickOutsideDeactivates for next (#302) (#303) (b12d6ce)

3.0.2 (2020-09-23)

Bug Fixes

  • watcher flush option to post (aa2582d)

3.0.1 (2020-09-18)

  • Build fixes

3.0.0 (2020-09-18)

  • Upgrade to focus-trap 6

2.0.1 (2020-08-07)

Bug Fixes

  • ignore comments for focus-trap (26586b7)

2.0.0 (2020-08-07)

Bug Fixes

  • change test config + make e2e pass (8e3a38f)