Usuarios que desplazan el chat mientras siguen las transmisiones sin interrumpir la lectura
Un desplazador de chat de React que sigue los mensajes en tiempo real cerca de la parte inferior, se congela cuando los usuarios desplazan hacia arriba y ofrece formas accesibles para volver abajo.
Fuentes: Building a chat interface that doesn’t fight the reader
Las decisiones de desplazamiento detrás de MessageScroller en beUI.
Desplaza hacia arriba para volver a leer una oración. El asistente sigue generando contenido. Otro bloque de tokens llega y la vista se mueve nuevamente a la línea más reciente.
Desplaza hacia arriba de nuevo.
Las burbujas de mensaje bien diseñadas no salvan una interfaz de chat que dificulta la lectura. Esa fricción es uno de los detalles de interacción abordados al crear beUI (beui.dev), una biblioteca de componentes React centrada en el movimiento y la interacción.
La pregunta de diseño de MessageScroller es específica: ¿cuándo debe la vista seguir al mensaje que se envía en tiempo real y cuándo debe permanecer en su lugar?
A continuación se muestra un estado
Un enfoque ingenuo consiste en desplazarse al final cada vez que hay un cambio en los mensajes. Esto funciona bien al ver la respuesta más reciente, pero falla en cuanto alguien quiere examinar el contexto anterior.
Trata estas situaciones como estados distintos:
- Siguiendo: el lector se encuentra cerca de la parte inferior, por lo que el contenido en crecimiento podría hacer que la vista se desplace hacia arriba.
- Leyendo mensajes anteriores: el lector ya ha dejado la parte inferior, así que la nueva información no debe hacer que vuelva a desplazarse hacia abajo.
La distancia desde la parte inferior de la región desplazable determina la decisión que toma beUI:
const distanceFromEnd =
viewport.scrollHeight -
viewport.scrollTop -
viewport.clientHeight;
const following = distanceFromEnd <= followThreshold;
El umbral por defecto es de 56 píxeles: un margen ajustable cerca de la parte inferior para que los movimientos mínimos no impidan inmediatamente el seguimiento del contenido.
Se evita intencionalmente la igualdad exacta. Los desplazamientos de desplazamiento pueden ser fraccionarios incluso cuando las mediciones de altura parezcan redondeadas; el comportamiento del atributo scrollHeight en los navegadores, documentado en MDN, lo señala claramente.
Observa cómo crece el contenido
A menudo, la transmisión en flujo modifica un mensaje existente en lugar de agregar una nueva fila. El número de mensajes puede mantenerse constante mientras un párrafo gana varias líneas adicionales.
beUI monitorea el contenedor de contenido con ResizeObserver. Cuando cambia su tamaño, vuelve a verificar si la función correspondiente sigue activa antes de desplazarse al final.
Eso relaciona el comportamiento con la geometría renderizada en lugar de asumir que cada cambio afecta el diseño. Las imágenes que se cargan o los resultados de herramientas ampliadas que modifican su altura son detectados de la misma manera: ResizeObserver existe específicamente para informar sobre los cambios en las dimensiones de los elementos.
Limitar el desplazamiento automático no congela el documento. Una imagen anterior sin espacio reservado aún puede desplazar hacia abajo al texto posterior. Un tamaño estable de los medios y un diseño predecible del mensaje siguen formando parte del funcionamiento del producto.
El lector necesita interrumpir
Los desplazamientos programáticos también emiten eventos de desplazamiento. Estos no deben interpretarse erróneamente como si el usuario hubiera elegido una nueva posición.
MessageScroller controla si está desplazándose por sí mismo. La entrada mediante rueda, los gestos táctiles y teclas como Page Up eliminan esa protección para que los eventos posteriores puedan actualizar la bandera correspondiente según el movimiento real del lector.
Esa distinción es importante cuando los tokens llegan de forma continua. Los fragmentos nuevos deben actualizar el texto de respuesta; no constituyen una excusa para quitarle el foco a un párrafo que alguien está leyendo.
Hacer que el regreso sea intencional
Después de que el lector llegue al final, el regreso debe ser deliberado.
MessageScroller puede mostrar una barra de navegación compacta sobre las filas de mensajes. Cada marcador incluye una vista previa del texto, lo que permite escanear hilos largos sin tener que ver todo el transcripción.
Elegir un marcador anterior desactiva la función de seguimiento y hace que el scroll se dirija hacia ese mensaje. Elegir el último marcador devuelve al final y vuelve a activar el seguimiento. Desplazarse manualmente hacia atrás dentro del umbral inferior también restablece la función de seguimiento.
El componente emite onFollowChange para que las aplicaciones puedan mostrar su propio control “Volver al último”. Ese control es responsabilidad de la aplicación; el rail es el navegador integrado.
Smooth debería seguir siendo opcional
El seguimiento suave está activado por defecto. Los usuarios pueden desactivarlo con la propiedad smooth, y el componente recurre al scroll inmediato cuando se solicita un movimiento reducido.
Cualquiera de los modos debería mantenerse mentalmente simple: seguir en la parte inferior, permitir leer por encima de ella y reanudar cuando el lector lo opte.
El movimiento de la vista no sustituye a las señales de accesibilidad. Muestre la transcripción como una región en tiempo real al estilo de registro, con actualizaciones corteses y una bandera que indique si está en uso; valide la combinación con su renderizador y lector de pantalla en lugar de asumir que los valores predeterminados son suficientes.
Pruebe cuando alguien desplaza la vista
Un diálogo breve y terminado no pondrá a prueba esta lógica. Prefiera una respuesta larga que siga transmitiéndose:
- Manténgase fijo en la salida más reciente y asegúrese de que las líneas nuevas permanezcan visibles.
- Muévase hacia arriba mientras sigan llegando nuevos datos y verifique que la vista no se arrastre hacia abajo.
- Utilice el teclado y la barra de mensajes para ir a conversaciones anteriores sin perder su posición.
- Vuelva al mensaje más reciente y compruebe que las conversaciones siguientes vuelvan a aparecer.
- Ejecute nuevamente las mismas pruebas con el movimiento reducido activado y con contenido cuya altura cambia (imágenes, paneles de herramientas).
Esos controles forman parte de lo que hace que la interfaz de usuario del agente sea considerada: la generación puede continuar mientras la atención se mantiene donde el lector la haya colocado.
La demostración de MessageScroller y su código fuente se encuentran en la sección de agentes del sitio beUI. Envíe un mensaje de demostración y luego desplácese hacia arriba mientras la respuesta se carga.