Accueil / Articles

Utilisateurs qui défilent le chat en suivant les flux sans interrompre la lecture

Un défileur de chat React qui suit les messages en temps réel en bas de l’écran, se fige lorsque l’utilisateur fait défiler vers le haut, et offre des moyens accessibles pour revenir en bas.

Éditeur : REACTAPP.TOP4 min de lecture845 mots

Sources: Building a chat interface that doesn’t fight the reader

Les décisions de défilement derrière MessageScroller de beUI.

Vous faites défiler vers le haut pour relire une phrase. L’assistant est encore en train de générer du contenu. Un nouveau groupe de tokens arrive, et la zone de visualisation revient à la dernière ligne.

Vous faites défiler à nouveau vers le haut.

Des bulles d’information bien conçues ne suffisent pas à sauver une interface de chat qui complique la lecture. Ce type de friction fait partie des détails d’interaction pris en compte lors de la création de beUI (beui.dev), une bibliothèque de composants React axée sur le mouvement et l’interaction.

La question de conception de MessageScroller est précise : quand la zone de visualisation doit-elle suivre la réponse en flux continu, et quand doit-elle rester en place ?

Voici un état possible

Une approche naïve consiste à défiler jusqu’en bas à chaque modification de message. Cela fonctionne bien pour consulter la réponse la plus récente, mais cela devient problématique dès que l’on souhaite examiner des contextes antérieurs.

Considérez ces situations comme des états distincts :

  • Suivre : le lecteur se trouve près du bas de l’écran, donc l’ajout de contenu peut faire monter la zone visible.
  • Lire des messages antérieurs : le lecteur a quitté la partie inférieure, donc de nouveaux contenus ne doivent pas le faire redescendre.

La distance par rapport au bas de la zone de défilement guide la décision prise dans beUI :

const distanceFromEnd =
  viewport.scrollHeight -
  viewport.scrollTop -
  viewport.clientHeight;
const following = distanceFromEnd <= followThreshold;

La valeur par défaut est de 56 pixels : une marge ajustable près du bas afin que de légères modifications ne désactivent pas immédiatement la fonction de suivi.

On évite délibérément une égalité exacte. Les offsets de défilement peuvent être fractionnaires, même si les valeurs de hauteur semblent arrondies — le comportement du scrollHeight des navigateurs, décrit sur MDN, le précise.

Observer l’évolution du contenu

Le streaming modifie souvent un message existant plutôt que d’ajouter une nouvelle ligne. Le nombre de messages peut rester constant tandis qu’un paragraphe gagne plusieurs lignes.

beUI surveille le conteneur de contenu à l’aide de ResizeObserver. Lorsque la taille change, il vérifie à nouveau si l’observation est toujours active avant de dérouler jusqu’à la fin.

Cela lie le comportement à la géométrie affichée plutôt que d’imaginer que chaque élément modifie le layout. Les chargements d’images ou les résultats d’outils agrandis qui changent de hauteur sont détectés de la même manière — ResizeObserver existe précisément pour signaler les changements de dimensions des éléments.

La limitation du défilement automatique ne fige pas le document. Une image apparue plus tôt sans espace réservé peut toujours pousser le texte qui suit. Une taille stable des médias et un layout prévisible des messages font toujours partie des fonctionnalités du produit.

Le lecteur doit intervenir

Les défilements programmés génèrent également des événements de défilement. Ceux-ci ne doivent pas être interprétés à tort comme le choix d’une nouvelle position par l’utilisateur.

MessageScroller surveille s’il effectue lui-même le défilement. Les entrées par roue, les gestes tactiles et des touches comme Page Up désactivent cette protection afin que les événements ultérieurs puissent mettre à jour le flag correspondant en fonction d’un véritable mouvement de lecture.

Cette distinction est importante lorsque les données arrivent continuellement. De nouveaux blocs devraient mettre à jour le texte de réponse ; ils ne constituent pas une raison de voler le focus d’un paragraphe que quelqu’un est en train de lire.

Rendre le retour intentionnel

Lorsque le lecteur atteint la fin, le retour doit être délibéré.

MessageScroller peut afficher une barre de navigation compacte au-dessus des lignes de messages. Chaque marqueur présente un aperçu du texte, permettant ainsi d’explorer des threads longs sans avoir à parcourir l’intégralité du texte.

En choisissant un marqueur antérieur, la fonction de suivi est désactivée et le scroll se dirige vers ce message. En choisissant le dernier marqueur, on revient à la fin et le suivi est réactivé. Un scroll manuel vers le bas au-delà du seuil inférieur restaure également la fonction de suivi.

Le composant émet onFollowChange afin que les applications puissent afficher leur propre bouton « Retourner au dernier message ». Ce contrôle relève de la responsabilité de l’application ; le rail constitue quant à lui le navigateur intégré.

La fonction de suivi fluide doit rester optionnelle

Le suivi fluide est activé par défaut. Les utilisateurs peuvent le désactiver avec la propriété smooth, et le composant passe alors à un scroll immédiat lorsque la réduction du mouvement est demandée.

Chacun de ces modes doit rester simple à comprendre : suivre le contenu en bas, permettre la lecture au-dessus, et reprendre le suivi lorsque l’utilisateur le souhaite.

Le mouvement de la zone de visualisation ne remplace pas les signaux d’accessibilité. Affichez le texte transcrit sous forme de zone en temps réel au style journal, avec des mises à jour courtoises et un indicateur d’activité ; validez la compatibilité avec votre moteur d’affichage et votre lecteur d’écran, plutôt que de supposer que les paramètres par défaut suffisent.

Testez le moment où quelqu’un défile

Un court dialogue terminé ne permettra pas de tester cette logique. Préférez une longue réponse qui continue d’être diffusée en continu :

  • Rester fixé sur la dernière sortie et s’assurer que les nouvelles lignes restent visibles.
  • Monter vers le haut tant que de nouveaux éléments arrivent, et vérifier que la zone de visualisation n’est pas tirée vers le bas.
  • Utiliser le clavier et la barre de messages pour accéder aux échanges antérieurs sans perdre sa position.
  • Revenir au dernier message et vérifier que les échanges suivants réapparaissent.
  • Répéter les mêmes vérifications avec le mouvement réduit activé, ainsi qu’avec du contenu dont la hauteur change (images, panneaux d’outils).

Ces fonctionnalités font partie de ce qui rend l’interface utilisateur d’un agent attentionnée : la génération peut se poursuivre tandis que l’attention reste là où le lecteur l’a placée.

La démonstration MessageScroller ainsi que le code source se trouvent dans la section consacrée aux agents sur le site beUI. Envoyez un message de démonstration, puis faites défiler vers le haut pendant que la réponse s’affiche progressivement.