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

Один компонент, больше чем одно визуальное состояние
Цена может быть active, changed-up, changed-down, suspended, stale, selected и pending-add. Если эти состояния кодируются разрозненными классами в разных экранах, поведение быстро расходится. Нужен единый component contract.
Данные отдельно, презентационное состояние отдельно
Компонент получает market state и возвращает семантическое действие select(selection_id, observed_version). Он не знает endpoint placement. Из потока данных вычисляется presentation state: направление изменения, доступность, label и допустимость взаимодействия.
Не озвучивать экранного диктора каждое движение цены
Live region на каждую дельту превращает интерфейс в поток шума. Изменения цены лучше отражать доступным названием при фокусе и визуальным индикатором, а важные состояния вроде suspend сообщать в контексте действия.
Фокус переживает обновление
DOM-элемент selection не должен пересоздаваться при каждом price update. Stable key и изменение текста внутри кнопки сохраняют focus. При suspend элемент остаётся в структуре, но становится disabled с объяснимым состоянием, вместо внезапного удаления.
Ожидание без таймаута
После нажатия добавления в betslip компонент может перейти в pending, но должен выйти из него по result, cancellation или timeout/reconciliation. Иначе единичный потерянный event оставляет кнопку навсегда «зависшей».
Что согласовать до сборки компонента
До верстки полезно зафиксировать не только набор визуальных состояний, но и источник каждого перехода. Рост или падение цены приходит из потока данных, suspend — из доменного состояния рынка, pending — из локального действия пользователя, а ошибка подтверждения — из ответа сервера. Если эти причины смешать, один и тот же цвет или label начинает означать разные вещи.
Для команды это означает простой контракт: дизайнер описывает состояние и приоритет, frontend связывает его с моделью данных, backend гарантирует однозначные причины недоступности. Такой договор уменьшает количество «почти одинаковых» состояний, которые потом трудно тестировать и объяснять пользователю.
- Зафиксировать приоритеты: suspend должен перекрывать декоративную индикацию движения цены.
- Проверить сценарий только с клавиатурой и при включённом screen reader.
- Отдельно протестировать быстрые последовательные обновления, когда цена меняется во время пользовательского действия.
Проверка на реальном потоке коэффициентов
Компонент удобно тестировать не отдельными snapshot, а короткой записью реального сценария: цена растёт, затем падает, рынок на секунду suspend, после чего возвращается. На каждом переходе смотрим три вещи: сохраняется ли выбранное состояние, остаётся ли focus на ожидаемом месте и не превращается ли обновление цены в поток лишних объявлений для screen reader.
Важно отделить информационное изменение от действия пользователя. Новая цена может подсветиться, но не должна выглядеть как подтверждение ставки. Когда выбор уже находится в betslip, LiveOddsTile сообщает новое состояние, а Betslip решает, нужен ли reprice перед подтверждением. Такое разделение не даёт одному визуальному элементу незаметно стать владельцем бизнес-решения.
В acceptance стоит добавить клавиатурный прогон: выбрать коэффициент, получить два обновления подряд, дождаться suspend и вернуть рынок в live. Если пользователь может завершить сценарий без потери контекста, компонент переживает live-режим, а не только красивый макет.
Компонентные ошибки видны в телеметрия
Считаются попытки действия в недопустимом state, focus restoration errors в e2e и доля stale controls. Это помогает ловить расхождение data-state и UI-state до массовых жалоб.

Связанные разборы по той же архитектурной цепочке
Страница спортивного события: как показать много рынков и не потерять контекст
Как устроить страницу спортивного события с большим числом рынков: стабильный контекст, группировка, быстрые обновления и метрики качества интерфейса.
Перейти к разбору →Букмекерская логикаКоэффициенты в реальном времени без шторма запросов
Путь коэффициента от поставщика до интерфейса: нормализация, снимки и изменения, версии, обратное давление и разветвление потока обновлений.
Перейти к разбору →Букмекерская логикаПоток коэффициентов и событий: путь данных от поставщика до экрана
Из каких участков складывается доставка коэффициента в реальном времени и где появляются очереди, рассинхронизация и устаревшие данные.
Перейти к разбору →ИнтерфейсыЦентр событий: точечные обновления без лишних перерисовок
Как обновлять центр спортивных событий точечно: нормализованное хранилище, подписки по сущностям и контроль частоты перерисовки интерфейса.
Перейти к разбору →