Skip to content

useFocusTrap

A Vue 3 composable that traps keyboard focus within a specified container element, preventing focus from escaping when using Tab or Shift+Tab keys. Useful for modals, dialogs, or any UI that requires focus to be constrained.

Installation

bash
npx kuro-ui add useFocusTrap
bash
npx github:Bartek-Nowak/Kuro add useFocusTrap

Usage

vue
<script setup lang="ts">
import { useFocusTrap } from '@/composables/kuro/useFocusTrap';

const { containerRef } = useFocusTrap();
</script>

<template>
  <div ref="containerRef" tabindex="-1">
    <!-- focusable elements inside -->
    <button>Button 1</button>
    <input type="text" />
    <button>Button 2</button>
  </div>
</template>

Description

  • Tracks all visible focusable elements inside the container.
  • Listens globally for keydown events.
  • When Tab or Shift+Tab is pressed:
    • If focus tries to move outside the container, it loops it back to the first or last focusable element.
  • Helps maintain keyboard navigation within modals/dialogs for accessibility.

Returned values

NameTypeDescription
containerRefRef<HTMLElement | null>Vue ref to bind the container element that traps focus

Details

Focusable elements include:

  • Links (a[href]), areas (area[href])
  • Inputs, selects, textareas, buttons (excluding disabled or hidden)
  • Iframes, objects, embeds
  • Elements with positive or zero tabindex
  • Contenteditable elements

Only visible elements (offsetParent !== null) are considered.

Keyboard listener is added with capture phase to prioritize focus trapping.

Notes

  • Ensure the container element has a tabindex if needed to receive focus.
  • This composable does not manage opening/closing of modals or focus restoration.
  • Intended to be used inside components that require keyboard focus confinement.