Vue component to trap the focus within a DOM element
Installation
For Vue 2
npm install focus-trap focus-trap-vue
For Vue 3
npm install focus-trap focus-trap-vue@next
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 theactive
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:
Do you accept the cookies?
<focus-trap v-model:active="isActive">
<modal-dialog tabindex="-1">
<p>
Do you accept the cookies?
p>
<button @click="acceptCookies">Yesbutton>
<button @click="isActive = false">Nobutton>
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:
What name do you want to use?
<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 namebutton>
form>
modal-dialog>
focus-trap>
Props
FocusTrap
also accepts other props:
escapeDeactivates
:boolean
returnFocusOnDeactivate
:boolean
allowOutsideClick
:boolean | ((e: MouseEvent) => boolean)
clickOutsideDeactivates
:boolean
initialFocus
:string | (() => Element)
Selector or function returning an ElementfallbackFocus
:string | (() => Element)
Selector or function returning an Element
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 activatesdeactivate
: Whenever the trap deactivates (note it can also be deactivated by pressing Esc 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:
Hello there!
<button @click="() => $refs.focusTrap.activate()">Show the modalbutton>
<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/davidtheclark/focus-trap