Всё про доступность интерфейсов
7 subscribers
116 photos
193 links
Download Telegram
Когда ошибка формы видна, но не слышна

Коротко: новый разбор issue → audit → PR по доступности интерфейса. Полный текст — следующим сообщением.
Когда ошибка формы видна, но не слышна

На этой неделе я выбрал Indico - систему для конференций и событий. Там нашёлся хороший пример не одной «кнопки без подписи», а связанной проблемы в общих интерфейсных паттернах.

В формах ошибка могла подсвечиваться цветом и всплывающей подсказкой, но само поле не получало нормальной связи с текстом ошибки. Для зрячего пользователя это заметно. Для пользователя со скринридером поле может звучать почти как обычное, без понятного «что исправить».

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

Я сдела PR, который чинит это на уровне общих механизмов: ошибки связываются с полями через aria-invalid и aria-describedby, выпадающие меню получают состояние открытия, а действия, зависящие от выбранной строки, уходят из порядка Tab, пока они недоступны.

Это хороший тест для любой команды: проверять нужно не только «есть ли текст ошибки на экране», а слышит ли пользователь связь между полем, ошибкой и следующим действием.

Кейс подготовлен с помощью Accessibility Auditor Skill.

Issue #7624: формы и ошибки
Issue #7625: панели действий
PR: indico/indico#7637
Когда голосовая клавиатура перестаёт быть доступной

В issue по Dictate Keyboard попал отзыв незрячего пользователя из Google Play: после обновления приложение «больше не доступно» с TalkBack и ещё одной программой экранного доступа, название которой, похоже, исказилось при переводе.

Здесь важна не сама фраза «не хватает подписей». Dictate Keyboard - это клавиатура для диктовки текста. Если пользователь не может найти микрофон, выбрать язык, запустить запись, проверить результат или воспользоваться плавающей кнопкой, он теряет не украшение интерфейса, а способ ввода.

В самом issue перечислены вероятные места поломки: кнопки-иконки без contentDescription, кастомные строки в настройках без роли и семантики, новый Smartbar, плавающая кнопка, диалоги и оверлеи, где фокус TalkBack может теряться или застревать.

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

Особенно у голосовых и AI-интерфейсов доступность держится на мелочах состояния. Кнопка должна быть видимой, называться, фокусироваться, говорить, что сейчас происходит, и не исчезать из маршрута экранного доступа после очередного «красивого» обновления.
Форма есть, но в неё нельзя попасть

В BlueBubbles для Windows открыли баг про стартовую настройку клиента. Пользователь с NVDA не может пройти форму подключения к серверу: поля адреса и пароля не попадают в обычный порядок Tab, а если найти их через объектную навигацию NVDA, текст всё равно не вводится.

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

В обсуждении появился ещё один похожий сигнал: голосовая диктовка Wispr Flow тоже не может корректно найти поле ввода нового сообщения в BlueBubbles и вставить продиктованный текст. То есть проблема бьёт не только по экранному доступу, но и по связке «диктовка + поле ввода».

Для команд вывод простой: форму нельзя проверять только глазами и мышью. Минимальный тест для Windows - пройти первичную настройку с клавиатуры и NVDA: Tab до каждого поля, понятное имя поля, настоящий фокус, ввод текста, ошибка, повторная попытка. Если поле видно, но не принимает ввод через доступный фокус, это не форма, а картинка формы.

Источник: BlueBubblesApp/bluebubbles-app#2965
DBeaver: настройка «для NVDA» может сломать доступ к таблице

В открытом баге пользователь описывает странный сценарий: включаешь screen reader type = NVDA, открываешь View data - и редактор данных перестаёт быть доступным.

Фокус не попадает в таблицу, стрелки не работают, меню не вызывается. Проверять нужно не наличие «режима доступности», а весь рабочий путь после его включения.

Источник: dbeaver/dbeaver#39720
Когда настройка «для NVDA» ломает саму таблицу

В DBeaver открыт баг: пользователь с NVDA включает в настройках интерфейса режим screen reader type = NVDA, открывает таблицу через View data - и редактор данных перестаёт быть доступным.

По описанию, фокус не попадает в таблицу, стрелки не работают, контекстное меню не вызывается. То есть проблема не в том, что таблица «не очень удобно читается». Пользователь фактически не может обследовать данные и работать с ними через клавиатуру и экранный доступ.

Важно, что это происходит именно после включения настройки, которая должна помогать NVDA. Автор повторно подтвердил воспроизведение на DBeaver 25.3.0 и позже написал, что проблема всё ещё актуальна на DBeaver 26.0.3 с NVDA 2025.3.3.

Для интерфейсов тут хороший урок: специальные режимы доступности нельзя считать автоматически полезными. Их нужно проверять как отдельный сценарий.

Если в продукте есть настройка «NVDA», «экранный диктор», «клавиатурный режим» или любой похожий флажок, тест должен быть очень приземлённым: включили настройку, открыли реальную таблицу, прошли по ячейкам стрелками, вызвали меню, изменили фокус, вернулись назад.

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

Источник: dbeaver/dbeaver#39720
GOV.UK: число и подпись должны звучать как одна фраза

VoiceOver и TalkBack читают текстовый Big number как два отдельных элемента. Визуально это один показатель, на слух - обрывки контекста.
Когда число и подпись распадаются на два элемента

В GOV.UK Publishing Components завели свежий issue про компонент Big number. Визуально он показывает одну фразу: например, «82 Open consultations». Но VoiceOver на iOS/macOS и TalkBack на Android читают текстовую версию как два отдельных элемента: сначала «82», потом «Open consultations».

Для зрячего пользователя это один показатель. Для пользователя экранного доступа это уже два фрагмента интерфейса, между которыми нужно догадаться о связи. В аудите GOV.UK прямо описали риск: человек может услышать «66», затем «Open consultations» и решить, что это разные ссылки или разные элементы, а не одно значение с подписью.

Интересная деталь: для JAWS и NVDA команда уже нашла отдельное исправление в PR #5458, но для VoiceOver и TalkBack текстовая версия всё ещё ведёт себя иначе. То есть «починили для одного набора экранных читалок» не равно «компонент стал доступным везде».

Если интерфейс собирает смысл из нескольких визуальных кусков - число, подпись, суффикс, статус, единицы измерения, - его нужно проверять на слух как одну пользовательскую фразу. Не только по HTML и не только в одном экранном доступе.

Хороший тест простой: закрыть глаза, пройти компонент VoiceOver/TalkBack/NVDA/JAWS и спросить себя: я слышу цельную мысль или набор обрывков, связь между которыми надо восстанавливать самому?
Kibana: кнопка показывает значение, но VoiceOver не слышит состояние

Свежий кейс про простую кнопку «показать / скрыть»: важно озвучивать не только имя действия, но и состояние после нажатия.
Кнопка «показать значение» должна говорить, что она уже включена

В Kibana завели свежий баг по VoiceOver: на странице Synthetics → Settings кнопка View parameter value показывает или скрывает значение параметра, но экранный доступ в обоих состояниях произносит одно и то же: «View parameter value, button».

Зрячий пользователь видит, что значок глаза поменялся и значение стало видимым или снова скрытым. Пользователь с VoiceOver этого состояния не получает. Он нажал кнопку, а дальше должен угадывать: значение уже открыто, закрыто или действие вообще не сработало.

В настройках мониторинга это не абстрактная мелочь. Там могут быть параметры окружения, адреса, токены, рабочие значения для проверок. Если интерфейс не сообщает состояние, человек не может уверенно управлять даже простой операцией «показать / скрыть».

Хорошо, что по issue уже открыт PR: в кнопку добавляют aria-pressed, а подпись меняется между «View parameter value» и «Hide parameter value». Для такого действия мало иметь доступное имя кнопки - нужно озвучить состояние после нажатия.

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

Источник: elastic/kibana#276962, связанный PR: #277162.
Меню видно, но экранный доступ его не открывает

В WordPress-теме Neve завели issue про выпадающее меню: пункт с подменю до него доходит, NVDA или TalkBack его озвучивает, но активация через экранный доступ может не раскрывать список. Мышью и обычной клавиатурой путь при этом выглядит рабочим.

По описанию, проблема не в одном пропущенном ярлыке. В desktop-варианте submenu control сделан как div role="button", обработчик клавиатуры слушает только Enter, click- и keyboard-состояния живут раздельно, а состояние раскрытия не отдано как aria-expanded. В итоге пользователь слышит контрол, нажимает его своим способом, но дочерние ссылки меню так и не становятся доступным маршрутом.

Это неприятный класс багов: интерфейс вроде бы «доступен», потому что элемент фокусируется и называется, но настоящая задача не выполняется. Для незрячего пользователя это значит простое: часть навигации сайта закрыта, хотя визуально она есть.

Что проверять командам: не только Tab и Enter в браузере, а активацию через NVDA/JAWS/TalkBack/VoiceOver. Если это меню, кнопка раскрытия должна быть настоящей кнопкой или вести себя как она: один общий механизм открытия, корректное aria-expanded, дочерние пункты доступны после открытия, состояние синхронизировано для мыши, клавиатуры и экранного доступа.
Когда список прокрутился, но экранный доступ молчит

В Flutter завели свежий issue про iOS и VoiceOver: пользователь делает обычную трёхпальцевую прокрутку в длинном списке, список действительно едет, но VoiceOver не говорит ничего вроде «страница 2 из 5» или «строки 6–10 из 43».

Для зрячего человека это легко не заметить: контент сдвинулся, значит прокрутка работает. Для незрячего пользователя это другая ситуация. Он сделал жест и не получил ответа, где теперь находится. В ленте, списке сообщений, настройках или аудиоприложении это быстро превращается в обследование вслепую: «я продвинулся? далеко? не перескочил ли нужный блок?»

Интересная деталь: автор сравнил iOS с Android. TalkBack получает события прокрутки и сам собирает объявление. На iOS строку статуса должен передать сам движок/приложение. В issue прямо указали место в Flutter engine, где для этого до сих пор стоит TODO. Комментарий участника Flutter подтвердил воспроизведение на iPhone: список прокручивается, но позиция не озвучивается.

Вывод для команд простой: проверять нужно не только «можно ли прокрутить». Нужно пройти реальный жест с VoiceOver/TalkBack и послушать, получает ли человек обратную связь после изменения позиции.

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

Источник: flutter/flutter#189285
Когда форма ошибается молча

Коротко: новый разбор issue → audit → PR по доступности интерфейса. Полный текст — следующим сообщением.
Когда форма ошибается молча

В OJS и OMP есть похожая проблема в формах регистрации и отправки материалов. Пользователь нажимает «отправить», форма показывает ошибки, но фокус может остаться на кнопке или улететь не туда. Для зрячего это неприятно. Для пользователя с JAWS или VoiceOver это уже риск потеряться: ошибка есть, но где именно чинить поле, непонятно.

Я выбрал для недельного PR не маленькую правку в одном месте, а общий слой валидации форм в pkp-lib. Там сходятся сразу три accessibility-issue: фокус после ошибки, связь поля с текстом ошибки и некорректный aria-invalid.

Что поменялось: после неудачной отправки фокус переходит к первому ошибочному полю, сообщение об ошибке получает стабильный id, поле связывается с ним через aria-describedby, а aria-invalid="true" ставится только пока поле реально невалидно.

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

Такие вещи хорошо ловятся не глазами, а обследованием интерфейса: что слышит экранный доступ, куда попадает фокус, понимает ли человек связь между полем и ошибкой. Для этого я и развиваю Accessibility Auditor Skill.

Issues: #12635, #12599, #12837
PR: pkp/pkp-lib#13031
Когда меню есть глазами, но его нет для экранного доступа

В репозитории OpenAI Codex появился свежий issue: в десктопном Codex на Windows меню подсказок открывается визуально, когда пользователь вводит /, но NVDA и JAWS его не видят.

Автор проверил это через Windows UI Automation: при открытии меню дерево доступности не меняется - 0 added, 0 removed, 0 changed. Фокус остаётся в поле ввода, стрелки двигают визуальное выделение, но экранный диктор не слышит ни список, ни текущий пункт.

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

Исправление здесь не сводится к «добавьте подписи». Такой компонент нужно проверять как комбинированное поле: поле ввода знает, что управляет списком, список имеет роль, варианты имеют состояние, а активный пункт меняется так, чтобы экранный диктор это объявлял. В веб-интерфейсах это обычно означает aria-haspopup, aria-controls, aria-activedescendant, role="listbox" и role="option" - но важнее не набор атрибутов, а реальная проверка с NVDA/JAWS.

Хороший тест для командных палитр, автодополнения и AI-инструментов: открыть меню с клавиатуры, пройтись стрелками и спросить не «вижу ли я подсветку», а «слышит ли пользователь, какой пункт сейчас выбран и что произойдёт после Enter».
Видео с субтитрами — это ещё не доступный видеоплеер

В Stagebook открыли отдельный issue по MediaPlayer: в компоненте есть свои кнопки play/pause, перемотка, шаг, скорость и поддержка файла субтитров через captionsFile. Но это как раз тот случай, где «субтитры есть» не закрывает задачу.

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

Хорошая проверка для команды простая: пройти медиасценарий без мыши и без звука. Видно ли, где фокус? Понятно ли экранному диктору, какая кнопка что делает? Можно ли включить субтитры и есть ли понятный путь к транскрипту? Учитывается ли prefers-reduced-motion, если в плеере есть движение?

Медиаплеер — это не один тег video. Это рабочий путь: управление, субтитры, текстовая альтернатива, клавиатура и состояние после каждого действия.
Drag-and-drop в учебном задании: если нельзя перетащить — нельзя учиться

В CodeSignal появился хороший, очень приземлённый баг-репорт: незрячий пользователь с NVDA проходит курс по генеративному ИИ и доходит до задания «заполни пропуски». Варианты ответа он может прочитать через мышиные команды, но положить слово в нужный пропуск не может — интерфейс ждёт перетаскивание.

Пример из отчёта простой: в предложении “Generative AI … creates blank 1 content” пользователь понимает, что правильное слово — “new”. Но знание ответа не помогает, потому что единственный способ ответить завязан на drag-and-drop.

Это важный тип поломки не только для незрячих. Drag-and-drop без альтернативы часто ломает задания для людей, которые работают с клавиатуры, switch control, голосовым управлением, трекболом, с временной травмой руки или на устройстве, где точное перетаскивание неудобно.

Хорошая проверка для таких заданий: можно ли выбрать вариант, назначить его конкретному пропуску, услышать/увидеть подтверждение и исправить ответ без мыши. Это может быть pick-and-drop с клавиатуры, список/комбобокс у каждого пропуска или другой понятный fallback.

Если пользователь знает правильный ответ, но не может ввести его в систему, проблема уже не в обучении. Проблема в интерфейсе задания.
.NET MAUI: поле говорит значение, но теряет смысл

В свежем issue по .NET MAUI Entry описали неприятный баг: у поля есть подпись User ID, есть AutomationProperties.Name и LabeledBy, но TalkBack и VoiceOver при фокусе произносят только текущее значение — например, TNTEST, Edit box.

Зрячий пользователь видит подпись рядом с полем. Пользователь экранного диктора слышит значение, но не слышит, что это за поле. В форме с несколькими заполненными полями это превращается в угадайку: где логин, где номер, где код, где сумма.

Кейс шире .NET-разработки. В формах нельзя проверять доступность только по наличию видимой подписи или ARIA/semantic-свойства в коде. Нужно пройти реальный сценарий с TalkBack/VoiceOver: фокус на поле должен давать и назначение поля, и текущее значение.

Если базовый компонент фреймворка теряет имя поля, команда всё равно отвечает за рабочий обходной путь: handler, platform-specific настройка, другой компонент или хотя бы запрет релиза критичной формы до исправления.
Файловый менеджер, где файлы есть, но до них нельзя добраться

В OpenList появился свежий issue от слабовидящего пользователя Android: приложение открывает интерфейс через WebView, но с TalkBack основной путь почти разваливается. Список файлов читается кусками: имя, размер и дата идут отдельными фрагментами, элемент не объявлен как файл или папка, а чекбокс выбора не говорит, какой файл он выбирает.

Ещё хуже с действиями. Скачать, переименовать, удалить, переместить или поделиться — это меню по долгому нажатию / контекстное меню. Для пользователя TalkBack такого “правого клика” фактически нет. Меню не получает фокус, пункты не объявлены как действия, и человек не понимает, как выполнить обычную операцию с файлом.

Это хороший пример, почему WebView сам по себе не делает мобильный интерфейс доступным. Если внутри живёт веб-интерфейс без ролей, подписей, фокуса и нормальных состояний, экранный диктор получает не приложение, а набор разрозненных текстов.

Для файловых интерфейсов стоит проверять не только “видно ли имя файла”. Проверьте весь путь с TalkBack: найти нужный файл, понять тип и метаданные, выбрать его, открыть меню действий, выполнить действие, услышать прогресс и ошибку. Если любой из этих шагов доступен только мышью, long press или визуальной догадкой — файловый менеджер для части пользователей просто не работает.

Источник: OpenListTeam/OpenList#2801.
TeXstudio и NVDA

Свежий кейс: кастомный редактор может выглядеть рабочим, но для экранного диктора быть почти пустым. Полный разбор ниже.
Когда редактор есть, а текста для NVDA нет

В TeXstudio появился свежий issue от полностью слепого пользователя NVDA: после создания файла основное поле редактора не читается нормально. NVDA не сообщает текст, нестабильно озвучивает ввод и не даёт надёжно понять, где стоит курсор.

Итог очень практичный: человек пишет LaTeX не в специализированной среде, а уходит в VS Code или даже Блокнот. Для студентов, исследователей и преподавателей, которые работают с формулами и большими документами, это не «неудобство», а потеря основного инструмента.

В связанной правке хорошо видно, где была проблема. Редактор TeXstudio - кастомный виджет с собственной отрисовкой. Визуально он существует, но для экранного диктора почти нет дерева доступности: нет текста документа, позиции курсора, выделения и событий при изменении содержимого.

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