Привет, Хабр.
Я — Senior Product Designer в проекте GlueLeague, зарубежной беттинг-платформе, сфокусированной на live-сегменте. В этом посте расскажу, как мы подошли к проектированию быстрого и предсказуемого интерфейса, в котором пользователи могут делать ставки в режиме реального времени, не теряя ориентир в хаосе обновляющихся коэффициентов. Под "мгновенным откликом" мы подразумевали не только скорость анимации или рендеринга, но и общее ощущение контроля и стабильности, особенно при высокочастотных обновлениях.

Контекст и вызов

Live-раздел в букмекерской платформе — это среда с максимальной плотностью изменений. Пользователь наблюдает за коэффициентами, которые обновляются каждые 200–500 мс, и принимает решение на основе динамичного контекста. Именно в этом сценарии критически важно минимизировать когнитивную нагрузку: элементы не должны смещаться, данные — исчезать, а действия — блокироваться. UX в live-ставках — это UX под давлением. Поэтому мы сформулировали следующие задачи:

  • Обеспечить стабильность layout при частых обновлениях данных;

  • Исключить неявные изменения интерфейса без визуального подтверждения;

  • Обеспечить предсказуемость клика: пользователь должен быть уверен, что он сделал ставку именно по тому коэффициенту, который видел.

Исходная архитектура и проблемы

В начальной версии интерфейс был построен на React с использованием SSR-рендеринга и периодического polling'а (1 раз в 3 секунды) для обновления коэффициентов. Это приводило к нескольким проблемам:

  • Полное обновление DOM при получении новых данных приводило к "прыжкам" карточек матчей;

  • Коэффициенты визуально менялись под курсором, из-за чего пользователи часто кликали не туда;

  • Не было различия между "успешной ставкой" и "ошибкой ставки": UI выглядел одинаково в обоих случаях.

Всё это приводило к фрустрации, высоким показателям rage click и росту количества обращений в поддержку.

Новый подход: реактивность и слой взаимодействия

В новой версии мы перешли к полной реактивной архитектуре на базе WebSocket-подписок. Каждая ставка, каждый коэффициент — это изолированный компонент, подписанный на конкретные события от сервера. Мы использовали Redux Toolkit с RTK Query для кэширования и нормализации данных. Обновления шли в батчах, агрегированных на бэкенде.

Для предотвращения визуальных скачков:

  • Визуальное обновление коэффициентов происходит через throttle (250–300 мс);

  • При изменении значения применяется анимация фоновой заливки (greenFade, redFade), но геометрия и положение DOM-узлов остаются фиксированными;

  • Обновления происходят через requestAnimationFrame и перерисовываются строго в пределах одного компонента, без каскадных перерисовок вверх по дереву.

UX-паттерны и принципы стабильности

Мы переосмыслили не только техническую сторону, но и UX-паттерны. Каждый компонент интерфейса, связанный с live-ставками, проектировался по принципу "максимальной визуальной инерции": если пользователь взглянул на экран, он должен в течение хотя бы секунды видеть ту же структуру.

  • Все блоки — карточки матчей, маркеты, кнопки ставок — имеют фиксированную высоту и padding;

  • Кнопки не исчезают: даже при блокировке ставки остаётся индикация "была попытка";

  • Обновление коэффициента никогда не приводит к визуальному сдвигу layout;

  • Sticky-бар с ключевыми действиями всегда закреплён внизу экрана и не перекрывается системными событиями.

Отдельный фокус на мобильный UX

Около 70% live-трафика — с мобильных устройств. Поэтому мы внедрили несколько решений, адаптированных под ограничения и сценарии смартфонов:

  • Свайпы влево/вправо переключают матч, свайп вверх — раскрывает маркеты;

  • Все активные действия доступны в зоне большого пальца (bottom-oriented CTA);

  • Кнопка ставки имеет увеличенную зону касания и блокируется на 800 мс после подтверждения действия;

  • Анимации упрощены до fade/scale, чтобы избежать перегрузки GPU при постоянных обновлениях.

Подтверждение действий и UX-ошибки

Ключевая UX-проблема — это отсутствие обратной связи в моменты, когда пользователь ожидает чёткой реакции от системы. Мы сосредоточились на проработке сценариев, где легко возникает неуверенность: изменился ли коэффициент, сработала ли ставка, произошла ли ошибка. Ниже — подробнее о внедрённых решениях.

  • При клике на коэффициент система сразу фиксирует намерение пользователя и отображает модальное окно. В нём отображается выбранный коэффициент, статус соединения и расчётное время ответа от сервера. Это помогает визуально зафиксировать, что ставка действительно в процессе и данные не "убежали".

  • Если коэффициент изменился между тем, как пользователь нажал кнопку и система попыталась отправить ставку, интерфейс не отменяет silently, а показывает всплывающее уведомление: "Коэффициент изменился. Подтвердите ставку повторно". Это диалоговое окно содержит как старое, так и новое значение, плюс кнопки выбора: согласиться на изменение или отказаться.

  • В случае, если сервер возвращает ошибку (например, ставка не принята, событие уже завершилось или превышен лимит), UI переключает карточку ставки в состояние "Ошибка". Отображается пояснение, включая тип ошибки (например, "истекшее событие"), и предлагается действие: обновить матч, выбрать другой исход или вернуться к списку событий. Это снижает фрустрацию и поддерживает ощущение управляемости происходящего.

Цифры и результат

После запуска новой версии мы собрали метрики с использованием собственного события ux:bet:attempt. Вот, что получилось:

Метрика

До редизайна

После

Rage clicks на live-экранах

12.4%

3.1%

Успешные ставки после 1 клика

71%

91%

Средняя скорость выбора ставки

1.9 сек

1.2 сек

Оценка удобства (по опросу)

3.7/5

4.6/5

Оценка платформы GlueLeague с позиции дизайна

Плюсы:

  1. Гибкая архитектура. Фронт-энд и бэкенд работают через событийную модель. Все ключевые взаимодействия реализованы по принципу pub/sub поверх WebSocket и внутреннего события-роутера. Благодаря этому, каждая сторона может независимо выкатывать фичи, минимизируя риски. Документация по событиям ведётся через Swagger, а для удобства тестирования используется собственный Viewer.

  2. Открытая коммуникация в команде. Мы используем связку Notion + Figma + Linear, где дизайнеры могут документировать UX-гипотезы, разработчики — сразу же брать их в работу и выкатывать на отдельные инстансы. Все процессы прозрачные, нет вертикального контроля — никто не блокирует улучшения ради формального «одобрения».

  3. Поддержка UX-инициатив. UX-решения инициируются самими участниками команды. Например, freeze-механизм при изменении коэффициента полностью разработан по инициативе дизайна и поддержан без сопротивления. В команде есть доверие к экспертизе, а не борьба за приоритеты.

Минусы:

  1. Отсутствие централизованной дизайн-системы. У нас нет общей библиотеки компонентов или системной стилизации (design tokens). Каждый продукт решает UI-задачи своими силами, что порождает дублирование, расхождение в поведении и лишние баги при масштабировании или рефакторинге.

  2. Слабая типизация событий. Форматы WebSocket-сообщений не унифицированы и часто меняются. Из-за отсутствия общего типа-описания приходится использовать runtime-валидацию (через zod/ajv), что добавляет рисков и снижает надёжность при CI-деплое.

  3. Устаревшая админка. Инструмент для внутренних операций не позволяет тестировать пограничные UX-кейсы. Например, невозможно быстро выставить нестандартный коэффициент или смоделировать задержку отклика. Это замедляет сценарное тестирование и требует обходных решений через backend-инженеров.

Вывод

Проектирование live-интерфейса — это не про «быстро и красиво». Это про создание среды, в которой интерфейс не мешает. Где пользователь не тратит лишние секунды, не пересматривает, не переспрашивает. Где он чувствует уверенность в моменте. И да, мы всё ещё улучшаем эту систему — но уже сейчас могу сказать: она действительно работает под нагрузкой и приносит пользователям то, чего им не хватает в других БК — контроль и предсказуемость.

Комментарии (0)