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

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

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

В issue сформулирован хороший минимум: сфокусированный блок можно сдвигать стрелками, например на 15 минут, менять длительность с клавиатуры, а новое время озвучивать через live region. То есть пользователь не должен угадывать: «сейчас 10:00-10:30 или уже 10:15-10:45?».

Это полезный тест для любых drag-and-drop интерфейсов: канбан, календарь, редактор таймлайна, сортировка карточек, настройка виджетов.

Если действие сделано через drag, рядом должен быть равный не-мышиный путь:

- фокус попадает на сам объект;
- есть понятные команды перемещения и изменения размера;
- после действия объявляется новое состояние;
- пользователь может отменить или проверить результат без зрения и без мыши.

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

В Kibana нашли две похожие проблемы. Пользователь открывает flyout Upload SIEM rules или Upload Splunk dashboards, а VoiceOver объявляет не видимый заголовок, а технический id: rulesMigrationDataInputFlyoutTitle / dashboardsMigrationDataInputFlyoutTitle.

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

Исправление: aria-labelledby у dialog/flyout должен ссылаться на элемент с реальным видимым заголовком, а не на внутренний ключ локализации или id.

Тест: откройте drawer/flyout с экранным диктором и послушайте первую фразу. Если она звучит не как заголовок на экране, сценарий начинается с путаницы.

Источник: elastic/kibana#285911, рядом #285917
Свежий пример из JLS: приложение может быть доступным в dev-запуске, но «немым» после установки, если в упакованный runtime не попал Java Access Bridge.

Ниже - полный разбор, почему доступность надо проверять на настоящем релизном инсталляторе, а не только в IDE.
В GitHub-issue по JLS поймали не баг в кнопках и не пропущенный aria-label, а более неприятную штуку: установленная Windows-версия Java-приложения может быть полностью «немой» для NVDA и JAWS.

Причина в сборке. Инсталлятор делает свой урезанный Java runtime через статический анализ зависимостей. А модуль jdk.accessibility, где лежит Java Access Bridge, туда сам не попадает: код приложения на него напрямую не ссылается. Плюс в поставке нет accessibility.properties, который включает мост.

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

Вывод для команд простой: доступность надо проверять не только в dev-запуске. Пройдите именно тот путь, который проходит пользователь: скачал релиз, поставил, открыл, включил NVDA/JAWS/VoiceOver/TalkBack и попробовал выполнить главную задачу.

Особенно это касается Electron, Java, Qt, Flutter desktop и любых приложений с упакованным runtime. Иногда доступность ломается не в интерфейсе, а в упаковке.
Лишняя кнопка тоже может ломать доступность.

В UI5 Web Components React завели issue про TabContainer: стрелка раскрытия рядом со вкладкой попадает в JAWS как отдельная кнопка More.

Визуально это маленькая стрелка. Но для screen reader она становится ещё одной командой в списке кнопок. Пользователь слышит лишний «More button» и должен угадывать, часть это вкладки или отдельное действие.

Проверка для команд: в вкладках, меню и split-button-паттернах ищите не только пропущенные подписи, но и лишний интерактивный мусор в дереве доступности.
Лишняя кнопка тоже может ломать доступность.

В UI5 Web Components React завели issue про TabContainer: у вкладки есть подпункты, рядом с ней визуально показывается стрелка раскрытия, и эта стрелка попадает в JAWS как отдельная кнопка More.

На экране это может выглядеть нормально: вкладка «General Information» и маленькая стрелка рядом. Но в JAWS Button List появляется ещё один отдельный элемент «More button menu». Пользователь слышит как будто две разные точки действия и должен угадывать, что это часть той же вкладки, а не самостоятельная команда.

Интересная деталь: в SAPUI5 reference похожая стрелка сделана декоративной: role="presentation" и aria-hidden="true". То есть screen reader видит саму вкладку и её состояние, но не техническую иконку рядом.

Вывод простой: доступность ломают не только невидимые кнопки. Иногда мешает наоборот лишний интерактивный мусор в дереве доступности.

Для вкладок, меню, раскрывающихся стрелок и split-button-паттернов стоит проверять не только Tab-порядок. Откройте список кнопок/ссылок в JAWS или NVDA и посмотрите, не появились ли там декоративные иконки, стрелки и внутренние «More», которые пользователь не должен выбирать отдельно.
Всё про доступность интерфейсов pinned «ВАЖНО: интересен и нужен ли вам этот канал?»
В VS Code есть хороший сигнал про доступность расширений.

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

Визуально всё есть: значок в редакторе, список закладок, состояние строки. Но с JAWS, NVDA, VoiceOver или Narrator приходится лезть в отдельный список и проверять вручную. Для инструмента навигации это почти ломает смысл функции.

Мейнтейнер ответил, что VS Code пока не даёт расширениям публичный API для таких невизуальных объявлений и accessibility signals. То есть проблема не только в одном плагине, а в границе платформы.

Что проверять: если статус показан иконкой, цветом, gutter, badge или звуком, нужен второй канал. Пользователь должен узнать: действие сработало, состояние изменилось, текущий объект уже в этом состоянии.
Dictus iOS: функция включается drag-жестом, а под VoiceOver этот путь исчезает. Хороший пример, почему у красивого жеста всегда должна быть понятная альтернатива.
У Dictus iOS нашли хороший пример: функция вроде бы есть, но для VoiceOver её нет.

Smart Mode включается длинным нажатием на кнопку микрофона, потом перетаскиванием на строку в веере и отпусканием. В обычном сценарии это быстрый жест. Но VoiceOver перехватывает долгий drag, а строки веера ещё и не являются accessibility elements. В итоге незрячий пользователь не может выбрать режим диктовки вообще.

Это не “чуть неудобнее”. Это другой продукт: зрячий пользователь меняет режим прямо в клавиатуре, а пользователь VoiceOver остаётся без основного действия.

Что здесь важно для интерфейсов:

• жест с drag не должен быть единственным способом выполнить действие;

• для iOS стоит добавить accessibility actions / rotor actions или отдельное действие в списке режимов;

• кнопка микрофона должна иметь понятное имя, состояние и текущий выбранный режим;

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

Если интерфейс держится на красивом жесте, простой контрольный вопрос такой: что сделает человек, который управляет телефоном не пальцем по экрану, а VoiceOver, switch control или голосом?

Источник: getdictus/dictus-ios#397
Свежий issue в Linksys PrivacyGUI: карточку dashboard можно переставить с клавиатуры, и на экране всё выглядит успешно.

Но после повторного открытия страницы карточка возвращается назад. Мышиный drag сохраняется, а клавиатурный путь нет.

Главный тест для drag-and-drop альтернатив: не только «можно ли двигать без мыши», но и «сохранился ли результат после Save/Done и повторного открытия экрана».
Клавиатурный путь должен сохранять результат, а не только красиво двигать карточку

Свежий issue в Linksys PrivacyGUI: на dashboard можно переставить карточку с клавиатуры. Пользователь входит в режим редактирования, Tab-ом доходит до карточки, нажимает Space, стрелками двигает её, снова Space, потом Done.

На экране всё выглядит нормально: карточка переехала. Даже семантическая подпись обновляется: было Row 1, Column 0, стало Column 1.

Но после повторного открытия страницы карточка возвращается назад. Мышиный drag сохраняется, Optimize сохраняется, а именно клавиатурный путь не пишет новое расположение в хранилище.

Это неприятный класс багов. Формально доступность как будто есть: фокус есть, клавиши работают, состояние озвучивается. Но реальная задача не выполнена. Человек с моторными ограничениями, пользователь клавиатуры, switch control или голосового управления тратит время, настраивает свой dashboard и молча теряет результат.

Здесь практический тест простой: если вы делаете drag-and-drop альтернативу, проверяйте не только сам жест.

Нужно пройти весь цикл:

1. выбрать элемент без мыши;
2. переместить или изменить его;
3. получить понятное подтверждение;
4. нажать Save/Done;
5. открыть экран заново;
6. убедиться, что результат сохранился.

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

В GitHub появился свежий issue по DRE Visualizations: после релиза нужно проверить MapLibre-контролы. Там уже увеличили кнопки навигации и закрытия попапа до 44×44 CSS px для coarse pointer - для пальца, стилуса и других неточных способов ввода.

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

Что я бы проверяла:

1. Тач-контролы не меньше 44×44 px.
2. Большая зона не перекрывает текст в попапе.
3. Управление работает с клавиатуры.
4. Фокус видно.
5. Закрытие, масштаб и прокрутка страницы не конфликтуют.

Доступность карт - это не только alt-текст. Иногда это нормальный размер кнопки, чтобы человек мог реально нажать её, а не играть в пиксельную охоту.

Источник: DRE Visualizations issue #13
Reduced motion как настройка продукта

В ProgressRPG завели issue про отдельный переключатель «уменьшить движение» в настройках аккаунта.

Предложение аккуратное: при первом открытии взять системный prefers-reduced-motion как подсказку, но дальше хранить выбор внутри приложения и дать человеку переопределить его.

Это помогает людям с вестибулярной чувствительностью, ADHD, мигренями и перегрузом от анимаций. Плюс обычный случай: пользователь может не хотеть менять всю ОС из-за одной игры, где двигаются прогресс-бары и эффекты level-up.

Для интерфейса урок такой: не пытайтесь «вычислить screen reader». Надёжного браузерного API для этого нет, и это вопрос приватности. А reduced motion - явная настройка. Её можно уважать, показать в интерфейсе и проверить на декоративных анимациях.

Мини-тест: включили настройку - переходы, автоскролл, эффекты прогресса и победы стали спокойными, а смысл экрана не потерялся.
Highcharts: график закрыли, а accessibility-таймеры ещё говорят.

Свежий баг про отложенные объявления в aria-live: старый компонент не должен подмешивать сообщения в новый экран.

Полный разбор ниже.
Свежий баг в Highcharts: график закрыли, а accessibility-таймеры продолжают работать.

В issue от 30 августа описан сценарий: график с accessibility.announceNewData.enabled ставит отложенное объявление для screen reader. Потом компонент уничтожают, но два таймера не очищаются. Один позже может объявить новые данные, второй - записать текст в уже отсоединённый live-region.

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

Что проверять:

• при размонтировании виджета очищаются все setTimeout/setInterval;

aria-live не объявляет события от старого состояния;

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

• на это есть регрессионный тест.

Доступность ломается и от тишины, и от лишней речи. Старый компонент не должен продолжать говорить.

Источник: Highcharts issue #25117
Видео без дорожки субтитров — это не «потом допишем текст».

В SCORM-проекте edumints-scorm-mcp завели issue: video screen выводит <video controls>, но без <track> и WebVTT. Статическая подпись и narration_text не заменяют синхронные субтитры.

Вывод для команд: проверяйте не только кнопку Play, а весь путь — captions track, доступный переключатель субтитров, transcript для audio-only и честную синхронизацию.
Видео без дорожки субтитров — это не «потом допишем текст».

Свежий сигнал из GitHub: в проекте edumints-scorm-mcp, который собирает SCORM-курсы, завели issue про video screen. Сейчас рендерер выводит обычный <video controls>, но без <track> и без WebVTT-пайплайна. В документации проекта это прямо записано как fail по WCAG 1.2.2.

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

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

Хороший вывод для продуктовых команд: если в интерфейсе есть обучающее видео, проверяйте не только кнопку Play. Минимальный рабочий набор — <track kind="captions">, WebVTT-файл внутри пакета, доступный переключатель субтитров, отдельный transcript для аудио-only сценариев и честная документация, где синхронизация приблизительная.

И важная мелочь: если субтитров нет, не называйте экран «доступным» только потому, что рядом есть текст. Для пользователя важен не факт наличия текста, а возможность следить за содержанием в нужный момент.
Форма, которую заполняют в 3 ночи

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

Это хороший пример, почему доступность формы - не список ARIA-атрибутов. Если шаги модального окна не переводят фокус на заголовок, клавиатура не может выбрать симптомы, ошибки не озвучиваются через live region, выбранные чипы отличаются только цветом, а анимации не уважают reduced motion - человек может просто не дойти до обращения за помощью.

Проверка для команды: пройти такой flow без мыши и глазами “как дизайнер” не считается. Пройдите его клавиатурой, VoiceOver/NVDA, крупным текстом и одной рукой. В конце должен быть не красивый wizard, а отправленная заявка и понятное состояние: что выбрано, где ошибка, что делать дальше.