Skip to content

useFocusTrap ​

Garde la tabulation dans un conteneur (panneau latéral, popover modal, menu mobile) et rend le focus à l'élément d'origine à la fermeture. Le Popover en mode modal l'utilise.

SuDialog n'en a pas besoin

Un <dialog> ouvert avec showModal() piège déjà le focus nativement et rend le reste de la page inerte.

Utilisation ​

vue
<script setup>
import { ref } from 'vue'
import { useFocusTrap } from '@surgeui/ds-vue'

const isOpen = ref(false)
const panelRef = ref()

// Actif tant que le panneau est ouvert
useFocusTrap(panelRef, { active: isOpen })
</script>

<template>
  <SuButton @click="isOpen = true">Filtres</SuButton>

  <aside v-if="isOpen" ref="panelRef" aria-label="Filtres">
    <SuInputField label="Recherche" />
    <SuButton @click="isOpen = false">Fermer</SuButton>
  </aside>
</template>

À l'activation, le focus va sur le premier élément focalisable (ou sur initialFocus). Tab passe du dernier au premier élément, Maj+Tab l'inverse. À la désactivation, le focus revient à l'élément qui l'avait avant.

Comportement ​

  • Pièges empilés : un piège ouvert dans un autre prend la main ; à sa fermeture, le précédent la reprend.
  • Contenu dynamique : les éléments focalisables sont recalculés à chaque Tab (champ ajouté, bouton désactivé…).
  • Focus parti à l'extérieur (clic, focus programmatique) : il est ramené dans le conteneur.
  • Restitution prudente : le focus n'est rendu que s'il est encore dans le conteneur ; si l'utilisateur a cliqué ailleurs, il n'est pas volé.
  • Conteneur vide : sans élément focalisable, le conteneur reçoit lui-même le focus (tabindex="-1").

Pour fermer avec Échap ou un clic à l'extérieur, combinez-le avec useDismiss.

API ​

ts
useFocusTrap(target, options?)

Options ​

OptionTypeDéfautDescription
activeMaybeRefOrGetter<boolean>—Active le piège tant que la valeur est vraie (sinon activate() / deactivate())
initialFocus(() => HTMLElement | null) | falsepremier élémentÉlément focalisé à l'activation ; false : le focus ne bouge pas
returnFocusboolean | (() => HTMLElement | null)trueÉlément qui reçoit le focus à la désactivation

Retour ​

PropriétéTypeDescription
activeReadonly<Ref<boolean>>Le piège est actif
activate() => voidActive le piège
deactivate() => voidDésactive le piège et rend le focus

Autres exports ​

ExportDescription
createFocusTrap(target, options?)Même piège, hors composant : { activate, deactivate, isActive }
getTabbableElements(container)Éléments atteignables par Tab, dans l'ordre du DOM

Migration

accessibility.trapFocus() est obsolète : il passe désormais par createFocusTrap et sera retiré dans une prochaine version majeure.

Publié sous licence MIT.