Utilities
Focus trap

Focus Trap

Trap focus within a specified container.

Motivation

Focus trapping is essential for modal interfaces and other interactive elements that require user attention.

The FocusTrap component helps maintain accessibility by ensuring keyboard focus remains within a designated container until explicitly released.

Examples

<script setup lang="ts">
import { FocusTrap } from '@ark-ui/vue/focus-trap'
import { ref } from 'vue'

const trapped = ref(false)
</script>

<template>
  <button @click="trapped = true">Start Trap</button>
  <FocusTrap :return-focus-on-deactivate="false" :disabled="!trapped">
    <div style="display: flex; flex-direction: column; gap: 1rem; padding-block: 1rem">
      <input type="text" placeholder="input" />
      <textarea placeholder="textarea" />
      <button @click="trapped = false">End Trap</button>
    </div>
  </FocusTrap>
</template>

Autofocus

The focus trap respects elements with the autofocus attribute.

<script setup lang="ts">
import { FocusTrap } from '@ark-ui/vue/focus-trap'
import { ref } from 'vue'

const trapped = ref(false)
const buttonRef = ref<HTMLButtonElement>()
</script>

<template>
  <div>
    <button ref="buttonRef" @click="trapped = !trapped">
      {{ trapped ? 'End Trap' : 'Start Trap' }}
    </button>
    <FocusTrap v-if="trapped" :disabled="!trapped" :set-return-focus="buttonRef">
      <div style="display: flex; flex-direction: column; gap: 1rem; padding-block: 1rem">
        <input type="text" placeholder="Regular input" />
        <input type="text" placeholder="Autofocused input" autofocus />
        <button @click="trapped = false">End Trap</button>
      </div>
    </FocusTrap>
  </div>
</template>

Initial Focus

Use the initialFocus prop to set the element that should receive initial focus when the trap is activated.

<script setup lang="ts">
import { FocusTrap } from '@ark-ui/vue/focus-trap'
import { ref } from 'vue'

const trapped = ref(false)
const inputRef = ref<HTMLInputElement>()
const toggle = () => {
  trapped.value = !trapped.value
}
</script>

<template>
  <div>
    <button @click="toggle">{{ trapped ? 'End Trap' : 'Start Trap' }}</button>
    <FocusTrap :disabled="!trapped" :initial-focus="() => inputRef">
      <div style="display: flex; flex-direction: column; gap: 1rem; padding-block: 1rem">
        <input type="text" placeholder="First input" />
        <input ref="inputRef" type="text" placeholder="Second input (initial focus)" />
        <textarea placeholder="textarea" />
        <button @click="trapped = false">End Trap</button>
      </div>
    </FocusTrap>
  </div>
</template>

API Reference