- 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>
119 lines
4.5 KiB
TypeScript
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();
|
|
}
|