veza/apps/web/src/utils/fixInputFocus.ts
senke 5cc720be8f refactor: Phase 3a — Global color class migration to SUMI semantics
- Replace all kodo-* color classes across ~100 TSX files:
  kodo-void → background, kodo-ink → card, kodo-graphite → muted,
  kodo-steel → muted-foreground, kodo-cyan → primary, kodo-magenta → destructive,
  kodo-lime → success, kodo-red → destructive, kodo-gold → warning
- Replace cyan-500, magenta-500, lime-500 default Tailwind colors with
  semantic equivalents (primary, destructive, success)
- Fix WaveformVisualizer hardcoded hex colors to SUMI values
- Delete global-effects.css (conflicting, redundant with index.css)

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 01:51:49 +01:00

119 lines
4.5 KiB
TypeScript

/**
* 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-border
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-primary/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();
}