Статус оплаты обновился, но скринридер об этом не сообщил

Разберём страницу оплаты: сначала появляется текст «Оплата подтверждена», затем — ссылка на закрытый Telegram-канал. Визуально всё работает. Но пользователь экранного диктора может не узнать об изменениях: фокус остался на кнопке, а обновлённый текст находится в другой части страницы.

Для таких сообщений подходит role="status". Эта роль задаёт live region с неявным aria-live="polite": сообщение может быть объявлено без переноса фокуса, когда скринридер сможет сделать это без прерывания текущего действия. Контейнер должен присутствовать на странице и иметь нужную роль до обновления текста. Рекомендации W3C

Сообщение о состоянии и ссылку лучше разделить:

У role="status" уже есть неявное aria-atomic="true". Здесь атрибут указан явно: W3C рекомендует это из-за различий поддержки в некоторых окружениях. Он указывает, что при изменении следует представить сообщение целиком. Описание техники ARIA22

Когда сервер возвращает новое состояние заказа, обновляем интерфейс. Этот код должен выполняться после создания элементов — например, из скрипта, подключённого с defer:

const statusNode = document.querySelector("#payment-status");const linkNode = document.querySelector("#channel-link");function renderPayment({ paid, inviteUrl }) { const ready = paid && Boolean(inviteUrl); const message = !paid ? "Ожидаем подтверждения оплаты." : ready ? "Ссылка для входа готова. Она находится ниже." : "Оплата подтверждена. Готовим ссылку на канал."; if (ready) { linkNode.href = inviteUrl; linkNode.hidden = false; } else { linkNode.hidden = true; linkNode.removeAttribute("href"); } if (statusNode.textContent !== message) { statusNode.textContent = message; }}

Это фрагмент отображения трёх состояний: ожидаем оплату, оплата подтверждена, ссылка готова. paid — булево значение, inviteUrl — проверенная сервером ссылка или null. Функция получает актуальное состояние одного заказа от своего бэкенда. Сам возврат с платёжной страницы подтверждением оплаты не считается.

Отказы, возвраты и ошибки запроса здесь не показаны. В рабочем интерфейсе для них нужны отдельные состояния: ошибка получения статуса не означает, что платёж не прошёл.

Контейнер статуса остаётся в DOM. При повторном ответе сервера с тем же состоянием его текст не перезаписывается. Это убирает ненужные изменения live region; поведение озвучивания всё равно нужно проверять в выбранной связке браузера и скринридера.

Ссылка находится вне live region. Статус сообщает о результате, ссылка позволяет перейти к следующему действию. При её появлении код не перемещает фокус: пользователь продолжает работать там, где находился.

Для ручной проверки нужно разнести изменения во времени:

  1. Включить скринридер и оставить фокус на кнопке проверки оплаты.

  2. Передать состояние paid: true, inviteUrl: null.

  3. После объявления сообщения передать состояние с готовой ссылкой.

  4. Проверить, что новое сообщение доступно без переноса фокуса.

  5. Несколько раз передать тот же ответ и проверить отсутствие лишних объявлений.

  6. Перейти к ссылке клавишей Tab и открыть её.

Если два состояния сменяются почти одновременно, не стоит рассчитывать, что скринридер обязательно произнесёт каждое промежуточное сообщение. Для этого сценария важно, чтобы пользователь узнал о готовой ссылке и мог до неё добраться.

В платёжном интерфейсе недостаточно обновить текст на экране. Изменение должно быть доступно пользователю, а следующий шаг — достижим с клавиатуры.

Источник: habr.com

0 0 голоса
Рейтинг новости
1
0
Подписаться
Уведомить о
0 комментариев