Liquid Glass avec React et TypeScript : interactions au pointeur
Une interaction Liquid Glass réussie répond au pointeur sans transformer chaque pixel en mise à jour React. Le DOM porte les coordonnées, CSS dessine la lumière et React conserve seulement l’état sémantique.

Séparer fréquence et sémantique
Les coordonnées du pointeur changent jusqu’à plusieurs dizaines de fois par seconde. Les stocker dans useState relance le rendu et mélange animation impérative et état applicatif. Écrivez plutôt deux propriétés CSS sur l’élément ciblé. React reste responsable de l’activation, de la désactivation et des variantes.
tsxfunction updateGlow(event: React.PointerEvent<HTMLElement>) { const node = event.currentTarget; const rect = node.getBoundingClientRect(); node.style.setProperty("--pointer-x", `${event.clientX - rect.left}px`); node.style.setProperty("--pointer-y", `${event.clientY - rect.top}px`); }
Typez le gestionnaire avec l’élément réellement utilisé. currentTarget reste alors sûr même si target désigne une icône enfant.
Échantillonner avec requestAnimationFrame
Sur une grille riche, regroupez les événements dans une frame. Gardez le dernier événement, annulez la frame en attente au démontage et n’effectuez qu’une lecture de géométrie avant les écritures CSS. Cela réduit les recalculs de layout et garde une trajectoire fluide.
Ne capturez le pointeur que pour un geste qui doit continuer hors de la cible, comme un slider. Un simple reflet de survol n’en a pas besoin. Sur tactile, ignorez généralement l’effet continu : la position du doigt masque la lumière et n’apporte pas de signal fonctionnel.
Dessiner le reflet en CSS
Un pseudo-élément peut utiliser un gradient radial centré sur les variables. Laissez pointer-events: none, limitez l’opacité et masquez le débordement. L’état pressé doit rester distinct : légère réduction d’échelle ou changement de bordure, sans dépendre de la position du reflet.
css.glass-card::before { content: ""; position: absolute; inset: 0; pointer-events: none; background: radial-gradient(280px at var(--pointer-x) var(--pointer-y), rgb(255 255 255 / 0.22), transparent 65%); opacity: var(--glow-opacity, 0); } .glass-card:hover { --glow-opacity: 1; }
Un composant utilisable partout
Exposez une API courte : intensity, interactive et asChild si votre bibliothèque le permet. N’exposez pas les coordonnées. La surface ne doit pas imposer un rôle ARIA; le composant consommateur choisit lien, bouton ou simple section.
Pour le clavier, :focus-visible fournit un état équivalent au survol. Pour la réduction des mouvements, désactivez interpolation et transformation, mais conservez l’anneau et la bordure. Une préférence utilisateur supprime le mouvement, pas l’information.
Nettoyage et tests
Nettoyez les frames et observateurs au démontage. Testez pointerleave, changement rapide de cible et redimensionnement. Un test de composant peut vérifier que les variables sont écrites; un test navigateur valide la trajectoire, le focus et l’absence de mouvement en préférence réduite.
Utilisez le profileur React : aucun commit ne devrait apparaître pendant un simple déplacement. Dans Performance, surveillez les layouts forcés et le coût de paint.
Cette interaction repose sur la base CSS progressive. L’étape suivante consiste à mesurer performance, compatibilité et accessibilité, avant de l’intégrer au design system React.
À lire ensuite
Liquid Glass : fondamentaux pour une interface lisible et cohérente
Comprendre les couches, la lumière, la profondeur et les limites du verre numérique avant d’ajouter le moindre blur.
CSSLiquid Glass en CSS : backdrop-filter accessible et robuste
Une recette CSS progressive avec tokens, fallbacks, contraste, préférences utilisateur et états clavier visibles.