Rendre une application prête pour Tuti Tuti

Tuti Tuti pilote une application web comme le ferait une personne attentive : il lit ce qui est à l’écran, trouve la chose qu’une phrase nomme, puis clique, tape ou pointe. Tout ce qu’il peut voir, il peut l’utiliser. Ce guide explique quoi bâtir dans une application pour qu’un script écrit en langage courant fonctionne du premier coup. C’est aussi, tout simplement, de l’accessibilité : les personnes qui utilisent un lecteur d’écran profitent du même travail. L’édition anglaise, docs/APP-GUIDE.md, suit la même numérotation.

Remettez ce fichier à la personne ou à l’IA qui construit l’application. La dernière section est un bloc à coller dans les consignes de projet d’un assistant de programmation.

1. Chaque contrôle porte un nom qu’une personne dirait

Tuti Tuti lit, dans cet ordre : l’étiquette d’accessibilité (aria-label ou aria-labelledby), le texte visible, l’infobulle (title) et le texte de remplacement d’une image. Un contrôle qui n’a rien de tout cela ne peut être trouvé que par sa couleur et sa position, ce qui reste fragile.

À faire <button>Nouvel entrepôt</button>
À faire <button aria-label="Ouvrir le menu"><ChevronIcon /></button>
À faire <button title="Notifications"><BellIcon /></button>
À éviter <button><BellIcon /></button> sans rien d’autre
À éviter du texte gravé dans une image ou un canevas

Nommez les choses comme le script les nommera. Si l’élément de la barre latérale dit « Achats », le script dit « allez dans Achats ». Une étiquette qui n’existe que dans un fichier de maquette n’est pas une étiquette.

2. Les étiquettes sont uniques sur un écran, ou portent leur contexte

Deux boutons qui disent tous deux « Supprimer » forcent Tuti Tuti à s’arrêter pour demander lequel. Préférez « Supprimer l’article » et « Supprimer l’entrepôt », ou donnez au second un aria-label qui dit ce qu’il supprime. Même chose pour « Modifier », « Enregistrer », « Plus » et les boutons à icône répétés à chaque ligne d’une liste : aria-label="Modifier Widget bleu".

3. Les champs disent ce qu’ils sont

Pour chaque champ de saisie :

  • Un vrai <label for> ou un <label> qui l’enveloppe, ou un aria-label. Un texte indicatif seul fonctionne, mais il disparaît dès que la saisie commence.
  • Le bon type : tel, email, number, date, password, url. Tuti Tuti lit le type comme un mot, alors « pour le numéro de téléphone, écrivez … » trouve un champ type="tel" sans étiquette.
  • autocomplete là où il s’applique (name, tel, email, organization). Il est lu lui aussi.
  • Les champs dans l’ordre où une personne les remplit. Quand un script tape dans « le prochain champ », Tuti Tuti va au prochain champ vide du même formulaire, dans l’ordre du document.
<label for="phone">Téléphone</label>
<input id="phone" type="tel" autocomplete="tel" />

La saisie se fait un caractère à la fois, avec de vrais événements input, alors les champs contrôlés de React, Vue et Angular se mettent à jour normalement. Les champs qui n’acceptent que du texte collé, ou qui reformatent à chaque frappe en déplaçant le curseur, peuvent faire échouer la saisie ; testez-les.

4. Les boîtes de dialogue, menus et tiroirs s’annoncent

Pendant qu’une boîte de dialogue est ouverte, Tuti Tuti privilégie ce qu’elle contient et écarte la page derrière. Il reconnaît une boîte de dialogue par <dialog open>, role="dialog", aria-modal="true", ou une classe contenant modal, dialog, drawer, sheet ou popover. Employez l’une des trois premières.

  • Fermé veut dire caché. Un tiroir glissé hors de l’écran est ignoré comme il se doit, mais un tiroir simplement en opacity: 0 par-dessus la page ne l’est pas. Employez hidden, display: none, visibility: hidden ou inert sur les surcouches fermées.
  • Les menus ont du texte. Les éléments de menu sont des liens ou des boutons avec du texte visible, pas des icônes seules.
  • Les onglets sont des onglets. role="tab" avec aria-selected, ou au moins des boutons qui portent le nom de l’onglet.
  • Les modes sont des boutons. Si dessiner ou modifier exige un mode, faites-en un bouton étiqueté (« Ajouter ou dessiner une allée »), pour que le script puisse l’activer dans sa propre phrase.

5. Les surfaces de dessin sont étiquetées

Un plan ou un canevas sur lequel on dessine devrait le dire : <canvas aria-label="Plan de l’entrepôt"> ou role="application" avec un aria-label. Les formes déjà dessinées, si ce sont des éléments SVG ou positionnés en absolu, sont détectées et évitées quand Tuti Tuti en place une nouvelle ; un canevas bitmap est opaque, ce qui convient ; attendez-vous seulement à ce que les nouvelles formes partent du centre.

6. Gardez l’interface principale dans la page

  • Pas d’iframe pour l’application elle-même. Tuti Tuti n’entre pas dans les iframes. Une vidéo intégrée, c’est bien ; la boîte de dialogue avec le bouton Enregistrer, non.
  • Le Shadow DOM convient. Les racines ouvertes sont explorées. Les racines fermées ne le sont pas.
  • Ne virtualisez pas les listes courtes. Les éléments qui n’existent pas dans le DOM avant d’être défilés ne peuvent pas être trouvés. Les longues listes dans un conteneur défilant conviennent tant que les éléments sont présents dans le DOM ; Tuti Tuti fait défiler le conteneur jusqu’à eux.
  • Pas de texte dans les images. Les étiquettes de boutons, les noms de menus et les titres sont du vrai texte.

7. Des ancrages stables survivent aux refontes

Tuti Tuti épingle chaque phrase à un élément en utilisant, dans l’ordre : data-testid, data-test, data-cy, un id écrit à la main, aria-label, name, href, des noms de classes stables, et enfin le chemin de l’élément. Les identifiants générés et les noms de classes hachés sont ignorés à dessein.

Ajouter data-testid="new-warehouse" aux contrôles qu’un tutoriel utilise, c’est faire en sorte que le tutoriel continue de fonctionner quand la mise en page change. C’est le geste le moins coûteux qui soit.

8. Évitez ce qui combat l’automatisation

  • Pas de vérification isTrusted sur les gestionnaires de clic. Les clics de Tuti Tuti sont des événements synthétiques (pointer, mouse, click, dans le bon ordre). Les applications qui exigent des événements de confiance les ignoreront.
  • Pas de contrôles essentiels révélés seulement au survol. Un bouton qui n’existe que pendant que la souris est sur une ligne reste atteignable en le faisant précéder d’une phrase « survolez », mais c’est une chose de plus qui peut mal tourner.
  • Pas d’actions réservées au clavier. Tout ce dont un tutoriel a besoin est cliquable.
  • Pas de confirm() ni de alert() sur les chemins qu’un tutoriel emprunte. Les boîtes natives bloquent la page et l’enregistrement.
  • Un rythme prévisible. Montrez un état de chargement, puis le contenu ; ne changez pas les étiquettes et ne déplacez pas les boutons sans raison après le premier rendu.

9. Dites quand les choses sont prêtes

Les boîtes de dialogue qui s’ouvrent en animation, les formulaires qui chargent leurs champs, les clavardages qui défilent jusqu’en bas une fois l’historique arrivé : pendant un instant, le contrôle existe, mais il n’est pas encore utilisable. Tuti Tuti attend, jusqu’à quelques secondes, que le contrôle soit activé, que rien au-dessus de lui ne soit marqué occupé et qu’il ait cessé de bouger. Rendez cette attente courte et certaine :

  • Marquez le chargement honnêtement. Mettez aria-busy="true" sur la boîte de dialogue ou le formulaire pendant qu’il se remplit, et retirez-le une fois terminé. Désactivez les champs et les boutons tant qu’ils ne fonctionnent pas (disabled, pas seulement grisés en CSS).
  • Mettez le focus sur le premier champ quand une boîte de dialogue s’ouvre. Un champ qui a le focus est le signal le plus clair de « tapez ici maintenant », et la première chose que Tuti Tuti cherche quand un script dit « tapez … » sans nommer de champ.
  • Finissez de bouger avant de vous déclarer prêt. Si un clavardage défile jusqu’en bas ou qu’un panneau glisse en place, laissez le mouvement se terminer avant d’activer la zone de composition. Gardez les animations courtes, un quart de seconde environ.
  • Ne déplacez pas la mise en page après le premier rendu sans raison. Un bouton qui bouge pendant que le contenu arrive fait atterrir le clic au mauvais endroit.

10. Donnez au tutoriel un état de démonstration

  • Un compte de démonstration ou une action de réinitialisation qui ramène l’application à un état connu, pour que le script corresponde à l’écran à chaque lecture.
  • Des valeurs de démonstration désignées : un numéro de téléphone d’entreprise pour les textos et les appels, un courriel de démonstration, des noms d’exemple. Le guide du script demande aux auteurs d’employer ces valeurs-là, jamais le numéro d’un inconnu.
  • Des données d’exemple suffisantes pour montrer la fonction : quelques articles, un entrepôt, deux ou trois commandes.

11. Liste de vérification

  • Chaque bouton, lien, onglet et icône a du texte visible, un aria-label ou un title.
  • Les étiquettes sont uniques par écran ou portent leur contexte (aria-label="Modifier Widget bleu").
  • Chaque champ a une étiquette et le bon type ; autocomplete là où il s’applique.
  • Les boîtes de dialogue emploient <dialog>, role="dialog" ou aria-modal ; les surcouches fermées sont vraiment cachées.
  • Les menus, onglets et modes sont des boutons ou des liens étiquetés, avec du texte.
  • Les surfaces de dessin ont un aria-label.
  • Pas d’iframe pour l’interface de l’application ; pas de racines Shadow DOM fermées ; pas de texte dans les images.
  • data-testid sur les contrôles qu’un tutoriel utilise.
  • Pas de vérification isTrusted, de boîtes natives ni d’actions réservées au clavier sur les chemins du tutoriel.
  • Les états de chargement emploient aria-busy et disabled ; les boîtes de dialogue mettent le focus sur leur premier champ ; les animations se terminent avant que les contrôles s’activent.
  • Un état de démonstration, des valeurs de démonstration et une réinitialisation.

12. Pour un assistant de programmation : collez ceci dans les consignes du projet

Cette application est pilotée par Tuti Tuti, un outil qui joue des tutoriels narrés sur l’interface en direct en trouvant les éléments par leur texte visible et leurs étiquettes d’accessibilité. Quand tu ajoutes ou modifies de l’interface : donne à chaque bouton, lien, onglet et contrôle à icône une étiquette de texte visible ou un aria-label (jamais une icône seule) ; rends les étiquettes uniques par écran ou ajoute le contexte dans aria-label ; donne à chaque champ une vraie étiquette et le bon type (tel, email, number, date) plus autocomplete là où il s’applique ; construis les boîtes de dialogue avec <dialog> ou role="dialog" et cache les surcouches fermées avec hidden ou display: none, pas avec l’opacité ; fais des menus, onglets et modes des boutons ou des liens étiquetés ; étiquette les surfaces de dessin avec aria-label ; garde l’interface de l’application hors des iframes et des racines Shadow DOM fermées ; mets data-testid sur les contrôles qu’un tutoriel utiliserait ; n’exige pas d’événements de confiance sur les gestionnaires de clic ; n’emploie pas alert() ni confirm() ; marque le chargement avec aria-busy="true" et disabled jusqu’à ce que les contrôles fonctionnent, mets le focus sur le premier champ quand une boîte de dialogue s’ouvre, et termine les animations et les défilements automatiques avant d’activer les contrôles ; et garde un état de démonstration avec des valeurs de démonstration désignées et une réinitialisation.

Le paragraphe anglais de la section 12 de docs/APP-GUIDE.md fonctionne tout aussi bien ; un assistant de programmation comprend l’un comme l’autre, alors collez celui qui est écrit dans la langue de vos consignes.