import {ref} from 'vue' /** * Détection de la modalité de focus (clavier vs souris/tactile). * * Sur les champs texte, `:focus-visible` natif se déclenche AUSSI au clic souris * (le navigateur suppose qu'on va taper). Pour n'afficher l'anneau de focus qu'à * la navigation clavier (Tab), on suit la dernière interaction au niveau document * et on n'arme l'anneau que si le focus a été précédé d'un évènement clavier. * * Le visuel « champ actif » existant (grossissement, label flottant, bordure bleue) * reste piloté par `:focus` et n'est pas affecté : ce composable ne gère QUE l'anneau. */ let hadKeyboardEvent = false let listenersAttached = false function ensureGlobalListeners() { if (listenersAttached || typeof document === 'undefined') return listenersAttached = true // capture=true pour observer l'évènement avant qu'il n'atteigne sa cible document.addEventListener('keydown', () => { hadKeyboardEvent = true }, true) const markPointer = () => { hadKeyboardEvent = false } document.addEventListener('mousedown', markPointer, true) document.addEventListener('pointerdown', markPointer, true) document.addEventListener('touchstart', markPointer, true) } export function useKbdFocusRing() { ensureGlobalListeners() const keyboardFocused = ref(false) const onFocus = () => { keyboardFocused.value = hadKeyboardEvent } const onBlur = () => { keyboardFocused.value = false } return {keyboardFocused, onFocus, onBlur} }