Користувачі чату, які переглядають трансляції без зупинки читання
Скролер чату у React, який відстежує повідомлення, що надходять, біля нижньої частини екрана, зупиняється, коли користувач прокручує вгору, та надає зручні способи для повернення вниз.
Джерела: Building a chat interface that doesn’t fight the reader
Рішення щодо прокручування у компоненті MessageScroller beUI.
Ви прокручуєте вгору, щоб перечитати речення. Асистент все ще генерує текст; з’являється черговий фрагмент даних, і вікно перегляду повертається до останнього рядка.
Ви знову прокручуєте вгору.
Гарно оформлені попередження не можуть врятувати інтерфейс чату, який ускладнює роботу користувача. Саме цей фактор є однією з проблем, які враховувалися під час створення beUI (beui.dev) — бібліотеки компонентів на React, орієнтованої на анімацію та взаємодію.
Завдання проектування MessageScroller є конкретним: коли вікно перегляду має слідувати за потоковою відповіддю, а коли залишатися на місці?
Нижче наведено стани
Наївний підхід полягає у прокручуванні до кінця після кожної зміни повідомлення. Це підходить під час перегляду найновішої відповіді, але стає проблематичним, коли потрібно переглядати попередній контекст.
Розглядайте ці ситуації як окремі стани:
- Підписка: читач знаходиться близько до низу, тому додавання нового контенту може підняти вікно перегляду.
- Читання попередніх повідомлень: читач вже вище низу, тому новий контент не повинен притягувати його вниз.
Відстань від низу регіону з прокручуванням впливає на рішення, яке приймається в beUI:
const distanceFromEnd =
viewport.scrollHeight -
viewport.scrollTop -
viewport.clientHeight;
const following = distanceFromEnd <= followThreshold;
Стандартний поріг становить 56 пікселів — це коригуваний діапазон біля низу, щоб навіть незначні зміни не призводили до негайної втрати можливості підписки.
Цілковита рівність навмисно уникається. Офсети прокрутки можуть бути дробовими, навіть якщо значення висоти виглядають округленими — це підтверджується описом поведінки параметра scrollHeight у браузері в MDN.
Спостерігайте, як зростає контент
Часто потокове формування контенту змінює вже існуюче повідомлення замість того, щоб додавати новий рядок. Кількість повідомлень може залишатися постійною, поки абзац отримує кілька нових рядків.
beUI стежить за контейнером вмісту за допомогою ResizeObserver. При зміні розміру він знову перевіряє, чи залишається певна функція активною, перш ніж прокрутити до кінця.
Це пов’язує поведінку з відображеною геометрією, а не припускає, що кожна зміна впливає на макет. Завантаження зображень чи розширення інструментів, які змінюють висоту, також фіксуються аналогічним чином — ResizeObserver призначений саме для відстеження змін розмірів елементів.
Обмеження автоматичної прокрутки не зупиняє роботу документа. Ранніше розміщене зображення без відведеного простору все одно може витіснити текст, розташований пізніше. Стабільний розмір медіа та передбачуваний макет повідомлень залишаються частиною функціоналу продукту.
Читач повинен перервати процес
Програмні операції прокрутки також генерують події прокрутки. Їх не слід сплутувати з вибором користувачем нової позиції.
MessageScroller відстежує, чи сам він здійснює прокрутку. Вхідні дані від колеса миші, жести сенсорного екрану та клавіші на кшталт Page Up знімають цей захист, щоб наступні події могли оновлювати відповідний флаг на основі справжнього руху читача.
Це розрізнення має значення, коли дані надходять безперервно. Нові фрагменти повинні оновлювати текст відповіді; вони не є підставою для відбирання уваги від абзацу, який читає хтось інший.
Робіть повернення навмисним
Після того, як читач досягає кінця, повернення має бути свідомим.
MessageScroller може відображати компактну навігаційну смугу над рядками повідомлень. Кожен маркер містить попередній перегляд тексту, щоб довгі повідомлення можна було сканувати, не переглядаючи весь текст повністю.
Вибір раннього позначника вимикає функцію слідкування та прокручує вікно до цього повідомлення. Вибір останнього позначника повертає вас до кінця та знову увімкнює функцію слідкування. Ручна прокрутка назад у межах нижньої межі також відновлює слідкування.
Компонент генерує сигнал onFollowChange, щоб додатки могли відображати власну кнопку «Повернутися до останнього». Цей елемент керування є справою додатку; сам же навігатор — це вбудований інструмент.
Функція плавної прокрутки має залишатися необов’язковою
Плавне слідкування увімкнене за замовчуванням. Користувачі можуть вимкнути його за допомогою атрибута smooth, і у разі запиту на скорочення руху компонент переходить на миттєву прокрутку.
Обидва режими мають залишатися простими з точки зору логіки: слідкування внизу, можливість читання над ним, продовження слідкування після того, як користувач це дозволить.
Рух вікна перегляду не є заміною сигналізації доступності. Відображайте транскрипцію у вигляді регіону в реальному часі у форматі журналу з ввічливими оновленнями та позначкою про зайнятість; перевіряйте сумісність із вашим рендерером та читачем екрана, а не припускайте, що стандартні налаштування достатні.
Перевірте момент, коли хтось прокручує сторінку
Короткий завершений діалог не дозволить оцінити цю логіку. Краще використовувати довгу відповідь, яка все ще транслюється:
- Залишайтеся прикутими до останнього результату та переконуйтеся, що нові рядки залишаються видимими.
- Піднімайтеся вгору, поки ще надходять дані, та перевіряйте, що вікно перегляду не притягується вниз.
- Використовуйте клавіатуру та панель повідомлень, щоб перемикатися на старіші розмови, не втрачаючи місця.
- Поверніться до найновішого повідомлення та перевірте, чи знову починаються наступні розмови.
- Повторно пройдіть ті самі перевірки з увімкненим скороченим рухом та з контентом, висота якого змінюється (зображення, панелі інструментів).
Ці функції є частиною того, що робить інтерфейс агента таким зручним: процес генерації може продовжуватися, поки увага користувача залишається там, де він її розмістив.
Демонстрація MessageScroller та вихідний код знаходяться у розділі agents на сайті beUI. Надішліть демонстраційне повідомлення, а потім прокрутіть вгору, поки надходить відповідь.