Всё про доступность интерфейсов
7 subscribers
116 photos
193 links
Download Telegram
Когда VoiceOver пропускает текст, это уже не «мелочь в markdown»

В react-native-enriched-markdown открыли свежий баг: на iOS VoiceOver не выбирает обычные абзацы и жирный текст. Автор приложил минимальный пример: заголовок, несколько абзацев, список, ссылка и выделенный текст. На Android с TalkBack этот же сценарий работает, а на iOS VoiceOver читает не всё.

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

В этом репозитории уже были старые исправления по VoiceOver: навигация по смысловым блокам, ссылки внутри абзацев, точность фокуса. Поэтому новый issue особенно показательный. Доступность rich text нельзя проверить один раз и забыть. После изменений в рендеринге, выборе текста, ссылках, списках и нативных слоях нужно снова пройтись экранным доступом.

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

Если приложение показывает важный текст через markdown, экранный доступ должен читать сам текст, а не случайно выбранные интерактивные островки.
Скрытый select тоже может мешать

В NetBox после аудита нашли неприятную вещь: скрытые нативные <select> за стилизованными выпадающими списками всё ещё попадают в дерево доступности.

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

Полный разбор ниже.
Скрытый select тоже может мешать

В NetBox после аудита завели свежую задачу: в форме фильтров скрытые нативные <select>, которые стоят за стилизованными выпадающими списками, всё ещё попадают в дерево доступности.

Для зрячего пользователя это выглядит как обычный красивый комбобокс. А JAWS при проходе по форме слышит лишний listbox, потом combobox, причём скрытый элемент ещё и без понятного имени. На длинной форме фильтров такой шум мешает: человек начинает сомневаться, где реальное поле, что сейчас выбрано и куда вообще попал фокус.

Рядом в том же аудите есть похожая проблема: у Saved Filter не озвучивается подпись, вероятно из-за дублей id и сломанной связи label → control. Вместе это хорошо показывает один класс ошибок: визуальная замена стандартного элемента не должна оставлять за собой «призрак» старого элемента для экранного доступа.

Что я бы проверял в таких местах: после инициализации Select2, Tom Select или любого своего комбобокса пройти форму с экранным диктором и инспектором доступности. В дереве должен остаться один понятный контрол: с именем, ролью, текущим значением и нормальным состоянием. Всё техническое, что больше не служит пользовательским полем, нужно убрать из дерева доступности или корректно скрыть.

Источник: NetBox issue #22530, смежная задача: #22531.
Календарь открылся - и NVDA начал читать всё подряд

В react-datepicker выбор диапазона дат внутри всплывающего окна привёл к странному эффекту: NVDA сразу зачитал все выбранные дни в случайном порядке.

Это не мелкая «болтливость» экранного диктора. Если календарь при открытии вываливает поток дат, пользователь ещё до выбора теряет контекст: где фокус, какой день активен и что делать дальше.
Календарь открылся - и NVDA начал читать всё подряд

В react-datepicker появился хороший пример неочевидной ошибки в календарях. Пользователь открыл выбор диапазона дат внутри всплывающего окна, а NVDA сразу начал зачитывать все выбранные дни в случайном порядке: 6 июня, 7 июня, 9 июня, потом 8 июня, потом снова дальше по сетке.

Фокус при этом мог стоять вообще не на календаре, а на другом элементе окна. Но для NVDA открылся диалог, он вошёл в режим чтения и прошёлся по содержимому. Календарь уже отрисовал много ячеек с aria-selected="true", поэтому пользователь получил поток дат вместо понятного состояния.

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

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

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

В Parla, нативном GNOME-клиенте для Delta Chat, пользователь описал простую проблему: списки чатов и сообщений открывают нужные действия только правой кнопкой мыши. С клавиатуры меню не вызывается.

Ожидаемый путь знакомый: Shift+F10 или клавиша контекстного меню. Но в списке чатов эти клавиши почему-то открывают меню поля ввода, а в списке сообщений не делают ничего. Для человека без мыши это уже не «неудобство», а закрытая часть продукта: действия над чатом или сообщением есть на экране, но до них нельзя добраться.

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

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

Источник: trufae/parla#40
VPN должен быть доступен без мыши

Свежий issue по AmneziaVPN: NVDA и TalkBack спотыкаются не только о подписи кнопок, а о весь путь управления VPN - серверы, вкладки, удаление профиля и split tunneling.
VPN должен быть доступен без мыши

В AmneziaVPN появился свежий issue про доступность основных экранов для NVDA на Windows и TalkBack на Android.

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

Особенно показателен Android-кейс: поле поиска приложений в split tunneling озвучивается как чувствительное или парольное, поэтому TalkBack не читает введённый текст нормально. А чекбоксы, по описанию автора, не включаются обычным жестом TalkBack - вместо двойного касания приходится удерживать элемент.

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

Вывод для команд простой: проверять нужно не только главный Connect. Пройдите весь путь с клавиатурой и экранным доступом: вкладки, выбор сервера, соседние кнопки действий, удаление, поиск, чекбоксы, состояния включено/выключено. У каждого интерактивного элемента должны быть понятные имя, роль, состояние и нормальная активация.

Источник: issue amnezia-vpn/amnezia-client#2778. Рядом открыт PR с правками доступности, но финальную проверку всё равно надо делать в реальной сборке с NVDA и TalkBack.
Когда окно «не модальное», оно не должно вести себя как ловушка

В Vaadin нашлась хорошая пара багов про один и тот же слой интерфейса: non-modal Dialog и Popover.

Визуально это выглядит как обычная плавающая панель поверх страницы. Но для клавиатуры и скринридера всё сложнее: диалог без затемняющего фона всё равно удерживал Tab внутри себя, а non-modal popover мог открыться без понятного объявления для NVDA и VoiceOver.

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

Я выбрал этот кейс для недельного PR: он не про один атрибут, а про общий паттерн overlay-компонентов. В PR non-modal Dialog больше не включает focus trap, а non-modal Popover получает polite-объявление своего текста или accessible name при открытии без переноса фокуса. Плюс добавлены регрессионные тесты.

Хорошая проверка для команд: если компонент называется non-modal, проверьте не только мышь. Уведите фокус за панель и нажмите Tab. Потом откройте такой popover со скринридером и убедитесь, что пользователь понял: что-то появилось и что именно.

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

Proof:
issue #11971
issue #11974
PR #11984
Когда ответ есть, но VoiceOver его не видит

В GitHub появился хороший сигнал по доступности Claude Desktop на macOS: полностью незрячий разработчик пишет, что может набрать и отправить запрос, но не может прочитать ответ ассистента через VoiceOver.

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

Обходной путь у автора показательный: читать ответы через iPhone companion app или внешне проговаривать их через macOS say. Для ежедневной работы это не решение. Человек пишет на Mac, ждёт ответ там же, а читать вынужден в другом месте или через отдельную самодельную озвучку.

Здесь ломается не «удобная мелочь», а главный цикл интерфейса: вопрос → ответ → продолжение работы. Для ИИ-продукта доступность стенограммы важна не меньше, чем доступность поля ввода.

Командам стоит проверять не только «можно ли что-то отправить», а весь разговорный поток: новый ответ объявляется, текст ответа есть в дереве доступности, до последнего сообщения можно быстро дойти, фокус не застревает, а изменения после серверного рендера не выбрасывают содержимое из VoiceOver/NVDA.
VS Code + VoiceOver: доступность ломается на скорости

Свежий сигнал: в VS Code Insiders большой файл с включённым VoiceOver может превращаться в почти нерабочий редактор. Полный разбор ниже.
Когда доступность ломается не на кнопке, а на скорости

В свежем issue по VS Code Insiders пользователь VoiceOver описал неприятную вещь: если открыть файл больше примерно 400 строк, редактор начинает сильно тормозить. С включённым VoiceOver и accessibility support процессор почти упирается в 100%, а задержка растёт вместе с размером файла. Расширения он отключал, то есть это не похоже на конфликт с плагином.

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

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

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

В issue по Frag Integreat проверяли чатбот сразу на Android, iOS и Windows. Для экранного диктора он местами превращается в один большой блок: нельзя пройти по ответу, нормально попасть в поле ввода, услышать новый ответ или удержать фокус внутри чата.

Проверять нужно весь разговор: открытие, поле вопроса, сообщения, объявление новых ответов, фокус и безопасное закрытие.

Источник: digitalfabrik/integreat-app#4223
Чатбот есть, а поговорить с ним нельзя

В Integreat завели отдельный issue по экранному доступу к Frag Integreat - их чатботу помощи. Проверяли сразу Android, iOS и Windows, и проблема не сводится к одной подписи на кнопке.

На Android экранный диктор несколько раз произносит «Frag Integreat», а весь блок чата воспринимается как один элемент. Из-за этого нельзя нормально пройти по ответу бота, выбрать часть текста и, что хуже, доступно ввести вопрос в поле ввода.

На iOS фокус иногда попадает не на ту кнопку: например, вместо меню можно оказаться на Back и случайно закрыть чат. На Windows при открытии и после ответа диктор уходит в заголовки или даже начинает читать страницу за чатботом, а новое сообщение не объявляется.

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

Я бы здесь проверял не «есть ли aria-label», а весь разговорный путь: фокус при открытии чата, отдельные элементы сообщения, доступное поле ввода, объявление новых ответов, удержание фокуса внутри чата и безопасное закрытие без случайного Back.

Источник: digitalfabrik/integreat-app#4223
Когда «следующее» сообщение оказывается предыдущим

В Expensify открыли issue про мобильный чат: с TalkBack включённым свайп к следующему элементу ведёт к предыдущему сообщению, а свайп назад - к следующему. То есть разговор читается в перевёрнутом порядке.

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

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

Командам стоит проверять не только «можно ли дойти до сообщения», а как читается весь разговор. Откройте чат с несколькими сообщениями, включите TalkBack или VoiceOver и пройдите его обычными жестами вперёд-назад. Если «следующее» и «предыдущее» меняются местами, это уже сломанная последовательность, даже если интерфейс визуально кажется правильным.

Источник: Expensify/App#94165
Открытый список - ещё не закрытый сценарий

Свежий issue в Forui: FSelect открыт, пользователь идёт по вариантам через TalkBack, доходит до конца - и следующий свайп уводит фокус на поле под списком. Поповер при этом остаётся открытым.

Вывод для команд: у выпадающих списков, меню и поповеров нужно проверять не только названия пунктов, а границу слоя. Пока слой открыт, TalkBack/VoiceOver не должны тихо проваливаться на страницу за ним.

Источник
Открытый список - ещё не закрытый сценарий

В Forui завели свежий issue про FSelect в Flutter. Сигнал конкретный: пользователь открывает выпадающий список, идёт по вариантам через TalkBack, доходит до последнего пункта - и следующий свайп уводит фокус на поле под списком. Сам список при этом остаётся открытым.

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

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

Мейнтейнер Forui ответил, что это упирается в ограничение Flutter OverlayPortal: один FocusScope удерживает клавиатурный фокус, но сам по себе не удерживает линейную навигацию TalkBack/VoiceOver. Для экранного доступа нужно отдельно проверять, что фоновые узлы убраны из дерева или слой действительно ведёт себя как отдельный маршрут.

Проверка для команд простая: откройте select, меню, поповер или похожий слой с включённым TalkBack/VoiceOver и пройдите его свайпами до конца. Фокус не должен тихо уходить на страницу под слоем. Если уходит - у вас сломан не “лейбл”, а граница сценария.
NVDA слышит «Data grid» - и на этом работа с субтитрами заканчивается

В Subtitle Edit v5.1.0-beta5 пользователь с NVDA описал редкий честный момент: часть доступности уже поправили, меню и многие подписи стали лучше. Но главный рабочий путь всё ещё ломается в месте, которое на вид может казаться обычной таблицей.

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

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

Здесь проверка не заканчивается на «у кнопок есть имена». В редакторах, админках и любых сложных инструментах нужно пройти весь рабочий путь с экранным доступом: меню, таблицы, горячие клавиши, поля ввода, изменение значений и возврат фокуса. Если таблица говорит только свою роль, а не содержимое, пользователь не управляет интерфейсом - он угадывает его.
VoiceOver не видит выбранные рубрики в WordPress iOS

В свежем issue по WordPress для iOS пользователь описал простой, но неприятный сценарий: при создании записи он открывает настройки статьи, доходит до рубрик и выбирает, куда отнести текст. Визуально выбранная рубрика есть, но VoiceOver не говорит, выбрана она или нет.

То есть человек слышит названия вроде «uncategorized», «books», «movies», но не получает состояния: какая рубрика уже выбрана, а какая нет. Для зрячего пользователя это мелкая отметка в списке. Для пользователя VoiceOver это риск опубликовать материал не туда или долго перепроверять действие вслепую.

Автор issue отдельно пишет важную вещь: не надо просто дописывать слова selected / unselected в текстовые метки. Правильнее сделать элемент нормальным переключателем или чекбоксом, чтобы состояние отдавалось через доступность как состояние элемента, а не как костыль в названии.

Для команд вывод простой: в списках выбора мало проверить, что пункт читается. Нужно пройти весь путь с экранным доступом и проверить имя, роль, значение и состояние: выбран / не выбран, отмечен / не отмечен. Особенно там, где ошибка меняет результат публикации, заказа, платежа или настройки.

Источник: wordpress-mobile/WordPress-iOS#25737
Когда ошибка формы видна, но не слышна

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