/** * Fix JavaScript pour le problème de focus sur les inputs * Détecte si le focus vient du clavier ou de la souris * et applique les styles en conséquence */ export function fixInputFocus(): void { if (typeof window === 'undefined') return; // Détecter si le focus vient du clavier (Tab) ou de la souris let lastInteractionType: 'keyboard' | 'mouse' | null = null; let keyboardNavigationActive = false; // Détecter la navigation clavier document.addEventListener('keydown', (e) => { if (e.key === 'Tab') { keyboardNavigationActive = true; lastInteractionType = 'keyboard'; // Réinitialiser après un court délai setTimeout(() => { keyboardNavigationActive = false; }, 200); } }, true); // Capture phase pour intercepter avant les autres handlers // Détecter les clics souris document.addEventListener('mousedown', () => { keyboardNavigationActive = false; lastInteractionType = 'mouse'; }, true); // Capture phase // Détecter les touches de navigation document.addEventListener('keydown', (e) => { if (['Tab', 'ArrowUp', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'Enter', ' '].includes(e.key)) { keyboardNavigationActive = true; lastInteractionType = 'keyboard'; setTimeout(() => { keyboardNavigationActive = false; }, 200); } }, true); // Appliquer les styles selon le type de focus const applyFocusStyles = (input: HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement, event?: Event) => { // Déterminer si c'est une navigation clavier const isKeyboard = keyboardNavigationActive || lastInteractionType === 'keyboard' || (event instanceof KeyboardEvent && event.key === 'Tab'); // Si c'est un clic souris, forcer le border steel (PAS de cyan) if (!isKeyboard && lastInteractionType === 'mouse') { input.style.setProperty('border-color', 'rgb(59, 69, 84)', 'important'); // border-kodo-steel input.style.setProperty('border-top-color', 'rgb(59, 69, 84)', 'important'); input.style.setProperty('border-right-color', 'rgb(59, 69, 84)', 'important'); input.style.setProperty('border-bottom-color', 'rgb(59, 69, 84)', 'important'); input.style.setProperty('border-left-color', 'rgb(59, 69, 84)', 'important'); input.style.setProperty('--tw-ring-width', '0px', 'important'); input.style.setProperty('box-shadow', 'none', 'important'); } else if (isKeyboard || lastInteractionType === 'keyboard') { // Si c'est le clavier, border cyan discret input.style.setProperty('border-color', 'rgba(102, 252, 241, 0.6)', 'important'); // border-kodo-cyan/60 input.style.setProperty('border-top-color', 'rgba(102, 252, 241, 0.6)', 'important'); input.style.setProperty('border-right-color', 'rgba(102, 252, 241, 0.6)', 'important'); input.style.setProperty('border-bottom-color', 'rgba(102, 252, 241, 0.6)', 'important'); input.style.setProperty('border-left-color', 'rgba(102, 252, 241, 0.6)', 'important'); input.style.setProperty('--tw-ring-width', '0px', 'important'); input.style.setProperty('box-shadow', 'none', 'important'); } }; // Observer tous les inputs const observeInputs = () => { const allInputs = document.querySelectorAll('input, textarea, select'); allInputs.forEach((input) => { const htmlInput = input as HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement; // Écouter les événements focus avec l'événement pour détecter la source htmlInput.addEventListener('focus', (e) => { applyFocusStyles(htmlInput, e); }, true); // Capture phase // Écouter les événements blur htmlInput.addEventListener('blur', () => { // Réinitialiser les styles htmlInput.style.removeProperty('border-color'); htmlInput.style.removeProperty('--tw-ring-width'); htmlInput.style.removeProperty('box-shadow'); }); }); }; // Observer les nouveaux inputs ajoutés dynamiquement const observer = new MutationObserver(() => { observeInputs(); }); // Initialiser if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', () => { observeInputs(); observer.observe(document.body, { childList: true, subtree: true, }); }); } else { observeInputs(); observer.observe(document.body, { childList: true, subtree: true, }); } } // Auto-exécuter if (import.meta.env.DEV) { fixInputFocus(); }