Aller au contenu principal
Site en cours de refonte — quelques pages peuvent bouger ou évoluer.
13 mars 2026

focusgroup : enfin une gestion du focus propre pour menus, tabs et popovers

Le focus, c’est là où l’accessibilité casse en prod. focusgroup veut rendre la navigation clavier prévisible, native et maintenable.

8 min de lecture
10 vues
réactions
Partager :
focusgroup : enfin une gestion du focus propre pour menus, tabs et popovers

Si tu veux une UI “pro” (menus, tabs, popovers) mais que tu veux aussi une navigation clavier fiable, tu finis presque toujours avec le même bricolage : du roving tabindex, des listeners keydown, des cas limites à n’en plus finir… et des régressions invisibles tant que personne ne teste au clavier. focusgroup (proposition côté Chrome) attaque exactement ce problème : donner au navigateur un moyen natif de gérer le déplacement du focus au sein d’un groupe, au lieu de te forcer à recoder un mini gestionnaire d’accessibilité à chaque composant.

Pourquoi la gestion du focus est un piège (même pour les équipes seniors)

Sur le papier, “gérer le focus” c’est simple : tu appuies sur Tab, tu avances. En réalité, les composants interactifs modernes demandent des règles plus riches :

  • Navigation directionnelle (flèches) dans une barre horizontale, une liste, une grille.
  • Conserver un élément “actif” sans rendre tous les items tabbables (sinon tu crées un enfer au clavier).
  • Focus qui traverse des couches : bouton → popover → contenu → fermeture → retour au bouton.
  • Compatibilité lecteurs d’écran : ARIA ok, mais si le focus “saute” ou se perd, c’est inutilisable.

Le résultat classique : tu implémentes un pattern “qui marche sur ton poste”, puis tu ajoutes un sous-menu, un item disabled, une recherche, du rendu conditionnel… et tu as une UX clavier incohérente. Et le pire : ce n’est pas toujours un bug visible à la souris, donc ça passe en prod.

focusgroup : l’idée (et ce que ça change vraiment)

focusgroup est une proposition (RFC) qui vise à standardiser la gestion du focus au sein d’un groupe d’éléments, typiquement :

  • menus et menubars
  • tabs
  • listbox / listes de résultats
  • grilles simples (ex : picker)

Le concept : tu déclares un conteneur comme “groupe de focus”, et le navigateur s’occupe de la logique de déplacement interne (souvent via les flèches), au lieu de te forcer à gérer :

  • qui a tabindex="0" vs -1
  • le wrap (fin → début) ou non
  • l’orientation (horizontal/vertical)
  • les items non focusables / disabled

Point important : c’est une proposition Chrome, la syntaxe et le comportement précis peuvent évoluer. L’objectif de cet article, c’est de te donner une stratégie d’adoption et des tests concrets, pas de te faire copier-coller un snippet qui sera obsolète dans 6 mois.

Les 4 cas concrets qui cassent le plus souvent (et comment focusgroup aide)

1) Menu horizontal (menubar) : le roving tabindex qui part en vrille

Le pattern “classique” : une barre avec 6 items, navigation aux flèches gauche/droite, Tab sort du composant. Le bug fréquent : tous les items deviennent tabbables, ou pire, le focus se bloque dans le menu.

Avec focusgroup, tu vises un comportement natif : Tab entre/sort, flèches déplacent à l’intérieur, sans que tu gères manuellement l’état tabindex de chaque item.

2) Tabs : focus vs sélection, et le mélange des deux

Sur des tabs accessibles, il faut distinguer :

  • focus (où est ton curseur clavier)
  • selected (quel onglet est actif, quel panel est affiché)

Beaucoup d’implémentations mélangent : on déplace le focus et on déclenche le changement de panel “à chaque flèche”, ce qui devient pénible et verbeux au lecteur d’écran. Une bonne UI a souvent deux modes : manual activation (Enter/Espace pour activer) ou automatic selon le contexte.

focusgroup ne remplace pas ARIA tabs ni ta logique d’affichage, mais il peut retirer la partie la plus fragile : le déplacement du focus entre les tabs, et laisser ta sélection (ARIA + panel) propre et testable.

3) Liste de résultats (search/autocomplete) : les “items” ne sont pas tous des boutons

Cas ultra courant : une liste de résultats où certains items sont des liens, d’autres des actions, d’autres encore sont désactivés. Tu veux naviguer aux flèches sans tabber 20 fois. Aujourd’hui, tu te retrouves à normaliser tout en pseudo-boutons focusables, puis à patcher les exceptions.

Un focusgroup bien utilisé peut rendre la navigation interne cohérente, tout en te laissant choisir la sémantique (liens, boutons, etc.).

4) Popover : le focus se perd, ou ne revient jamais au bon endroit

Le popover, c’est le cimetière des “petits hacks JS” :

  • ouvrir → où va le focus ?
  • Tab → est-ce qu’on doit piéger le focus (dialog) ou juste naviguer (popover léger) ?
  • Escape → qui reprend le focus ?

focusgroup n’est pas un focus trap universel, et ce n’est pas un remplacement direct de <dialog> quand tu as besoin d’un vrai mode modal. Mais dans un popover non-modal (menu déroulant, suggestions), focusgroup peut solidifier la navigation à l’intérieur du contenu, pendant que toi tu gères l’ouverture/fermeture et le retour au déclencheur.

À quoi ressemble une adoption réaliste (sans casser ton design system)

Si tu as déjà une base JS “maison”, l’objectif n’est pas de tout jeter. L’objectif est de réduire la surface de code fragile là où ça te coûte le plus cher en maintenance et en bugs.

Étape 1 : cartographier tes composants “à flèches”

Fais simple : liste les composants qui utilisent keydown pour gérer le focus :

  • tabs
  • menus
  • listbox / dropdowns
  • pickers

Ce sont tes candidats focusgroup.

Étape 2 : garder les patterns ARIA, enlever le JS de navigation

Ce que tu veux conserver :

  • la sémantique HTML (liens, boutons)
  • les rôles ARIA nécessaires (tabs, menu, etc.)
  • la logique “selection/activation” (Enter/Espace)

Ce que tu veux supprimer (ou rendre optionnel) :

  • roving tabindex mis à jour à la main
  • le calcul “prochain élément focusable”
  • les hacks pour ignorer les disabled, gérer le wrap, etc.

Étape 3 : progressive enhancement (indispensable)

Comme focusgroup est une proposition, tu dois le traiter comme une amélioration progressive :

  • si le navigateur supporte → moins de JS, meilleure cohérence
  • sinon → ton fallback JS continue de fonctionner

Concrètement : structure ton code pour que la navigation fléchée soit une “option”, pas un prérequis à l’usage du composant.

// Pseudo-approche: activer un fallback seulement si focusgroup n'est pas là.
// La détection exacte dépendra de la forme finale de la spec.

export function enhanceRovingFocus(container) {
  // 1) Si le navigateur gère nativement, ne fais rien.
  // 2) Sinon, active ton roving tabindex actuel.

  const hasNative = container.matches?.('[focusgroup]');
  if (hasNative) return;

  // Fallback minimal (existant chez toi) :
  // - écouter keydown
  // - déplacer le focus
  // - gérer tabindex 0/-1
}

Les tests clavier à automatiser (ceux qui attrapent 80% des régressions)

Si tu veux que focusgroup (ou ton fallback) améliore vraiment la qualité, il faut arrêter de “tester au feeling”. Automatisation + quelques checks UX, et tu passes un cap.

Checklist de base (menus, tabs, listes)

  • Tab entre dans le composant une seule fois (un seul stop), puis Tab en ressort.
  • Flèches déplacent le focus de manière prévisible (orientation + wrap si voulu).
  • Disabled est ignoré (tu ne peux pas focus un item disabled).
  • Home/End (si supporté dans ton pattern) va au début/à la fin.
  • Escape ferme un popover/menu et rend le focus au déclencheur.
  • Focus visible : pas de outline: none sans alternative.

Un indicateur UX simple à mesurer : “nombre de Tab pour accomplir X”

Le signal le plus bête (et le plus parlant) : combien de pressions de Tab/flèches pour :

  • atteindre le 5e item d’un menu
  • changer d’onglet et atteindre le 1er champ du panel
  • sélectionner le 3e résultat d’une liste

Si ton design system force 12 Tabs là où 2 flèches suffisent, tu as un problème d’UX clavier, même si “ça marche”. focusgroup vise justement à rendre ce genre d’optimisation moins risquée.

Ce que focusgroup ne fera pas à ta place

Il y a un piège : croire que “natif” = “magique”. Même avec focusgroup, tu dois rester carré sur :

  • La sémantique : un lien reste un lien, un bouton reste un bouton.
  • ARIA : tabs, menu/menuitem, aria-selected, aria-controls… focusgroup n’invente pas ton modèle d’accessibilité.
  • La gestion des couches : ouvrir/fermer, click outside, Escape, restauration du focus.
  • Le focus visible (et un thème contrasté) : sinon tu as juste un focus “correct” mais invisible.

Stratégie de rollout en équipe (pragmatique)

  • Commence par un composant (tabs ou menu), pas tout le design system.
  • Verrouille une suite de tests clavier avant de basculer, pour prouver que tu ne régresses pas.
  • Garde un fallback tant que la spec est RFC (et tant que le support n’est pas stable partout).
  • Documente une règle : “un seul stop Tab par composant composite” (quand c’est pertinent).

Si tu fais ça, focusgroup devient un levier de qualité. Sinon, ce sera “encore une API Chrome” que personne n’ose activer.

Conclusion : pourquoi ça vaut le coup de s’y intéresser maintenant

Le focus, c’est rarement un sujet “sexy”, mais c’est un sujet qui se paye cash : support, bugs fantômes, audits accessibilité, frustration utilisateur. focusgroup a une promesse simple : sortir la navigation du focus de ton JavaScript fragile pour la remettre là où elle devrait être depuis longtemps : dans la plateforme.

Tu n’as pas besoin d’attendre que tout soit finalisé pour en tirer de la valeur : dès maintenant, tu peux identifier tes composants à risque, isoler ton fallback, et écrire des tests clavier qui te rendront meilleur… avec ou sans focusgroup.

Sources

Cet article vous a plu ?

Commentaires

Laisser un commentaire

Entre 10 et 2000 caractères

Les commentaires sont modérés avant publication.

Aucun commentaire pour le moment.

Soyez le premier à donner votre avis !