- PVSM.RU - https://www.pvsm.ru -
Люди которые пишут стандарты — очень хитро устроились. Им достаточно написать как должно все хорошо работать, а дальше уже не их проблемы.
Примерно так и получилось с тем «как должны работать диалоги», точнее «правильные» с точки зрения a11y модальные диалоги.
В описание к dialog role на MDN [1] все написано очень просто:
Проблема в том, что MDN забыла еще об одном важном пункте, а все остальные забыли про один из сказанных – про то, что модал не должен выпускать фокус из своих рук. Активный элемент надо посадить под замок. Не дать ему сбежать из нашей ловушки.
История началась совсем недавно — в рассылке Веб-стандартов попалась мне ссылка на «правильный» WAI-ARIA Dialog [2]. И понеслось.
Компонент на самом деле хорош:
Те он делает все что просит MDN и даже больше, так как без первого пункта «выйти» из диалога с активированным screen reader — не составляет никакого труда.
В общем — must have!
Но вот реализация "focus-management [3]" немного подкачала — ребята реально перехватывают keyboard events(и не только) и эмулируют кнопку tab самостоятельно.
Настолько уму не постижимо, что я решил немного покопать как «это» вообще должно работать. Под словом «покопать» подразумевается проверить как различные сайты и фреймворки справляются с табами.
Начнем с сайтов (немного предвзятая выборка):
Вывод простой — у «нормальных» сайтов немного не хватает мозгов, а Яндексу руки оторвать.
С фреймворками (немного предвзятая выборка) сильно интереснее:
И вообще это самый кривой код из всех тут представленных, даже ссылку давать неприятно — github.com/react-component/dialog/blob/master/src/Dialog.tsx#L133 [5]
С фреймворками оказывается тоже совсем плохо. И совсем никто-никто не вешает aria-hidden на остальной контент, чтобы сделать модал на самом деле доступным для людей, которые вынуждены использовать скрин-ридеры.
На самом деле я тоже раньше совершенно не заморачивался всей этой фигней, но тут, как на зло, моя дорогая жена решила научиться верстке в HTML Academy где pepelsbey [9] с большой-большой компанией заставили и ее и меня задуматься над вопросом насколько таббабельный у меня сайт.
Пришлось и науку новую выучить, и проблемму решить с фокусом.
PS: Вадим рекомендует забить на всю эту aria-hidden с focus-management и воспользоваться html атрибутом inert, который просто «выключит»(врям совсем) все кроме модала и проблем нет будет ни с screen/reader, ни с фокусом.
Хотя насчет второго не уверен, да и работает он пока не очень, а полифилы просто ужасающие.....
В общем, как говорили на улице Льва Толстого… – а какие же ваши предложения.
На самом деле проблема очень проста — не смотря на то, что для JS было написано миллионы модулей — модулей для focus management фактически нет.
В общем 7 бед = +1 новый велосипед. А точнее настоящий поезд из focus-lock [15], dom-focus-lock [16], react-focus-lock [17] и vue-focus-lock [18] — на все случаи жизни.
Со стороны обертки (react, vue, dom) все очень просто — получить DOM ноду и закрыть в ней фокус. Вся соль именно в focus-lock.
Причин создания новой библиотеки несколько:
Так что пришлось сделать очередной велосипед, который временно отвечает чуть большему списку свистелок, чем его ближайшие конкуренты. Или конкретно всем.
Просто оберни модалы(и не только модалы) в FocusLock — и половина проблем будет решена (демо [19]).
<FocusLock>
<Modal>
any data
</Modal>
</FocusLock>
Но только половина, так как aria-hidden (или inert) вешать прийдется кому-то другому и куда-то в другое место. Но это уже другая история.
Итого не забывай %username%, что модалы — это не только серенький лайтбокс, что не прокликивается мышкой, но и дивный мир клавиатурных упражнений.
Но самое главное — не забывай что не надо мешать пользователю оперировать с сайтом не только мышкой.
PS: А еще лучше включить VoiceOver или другой ScreenReader и попробуйте свои сайты на прочность. Будете удивлены.
Многие вещи, например «ручная клавиатурная навигация» в ЯндексПочте — дефакто не не меняет активный элемент.
Одного програмиста из Финляндии [20] Яндекс точно потерял как пользователя.PPS: Gmail, правда, не так чтобы сильно лучше.
Автор: kashey
Источник [21]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/javascript/264071
Ссылки в тексте:
[1] dialog role на MDN: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_dialog_role
[2] WAI-ARIA Dialog: http://davidtheclark.github.io/react-aria-modal/demo/
[3] focus-management: https://github.com/davidtheclark/focus-trap
[4] github.com/jquery/jquery-ui/blob/master/ui/widgets/dialog.js#L300: https://github.com/jquery/jquery-ui/blob/master/ui/widgets/dialog.js#L300
[5] github.com/react-component/dialog/blob/master/src/Dialog.tsx#L133: https://github.com/react-component/dialog/blob/master/src/Dialog.tsx#L133
[6] github.com/palantir/blueprint/blob/master/packages/core/src/components/overlay/overlay.tsx#L312: https://github.com/palantir/blueprint/blob/master/packages/core/src/components/overlay/overlay.tsx#L312
[7] github.com/twbs/bootstrap/blob/900da3e235305c2daefe86c0a960e36be6e1b60b/js/src/modal.js#L280: https://github.com/twbs/bootstrap/blob/900da3e235305c2daefe86c0a960e36be6e1b60b/js/src/modal.js#L280
[8] bitbucket.org/atlassian/aui/src/92b8ce839ef1b6f320fe6a590def1cbc40cd2724/src/js/aui/focus-manager.js: https://bitbucket.org/atlassian/aui/src/92b8ce839ef1b6f320fe6a590def1cbc40cd2724/src/js/aui/focus-manager.js
[9] pepelsbey: https://habrahabr.ru/users/pepelsbey/
[10] focus-manager: https://github.com/IsaacAndela/focus-manager
[11] отличным примером: http://isaacandela.github.io/focus-manager/
[12] ToleFocus: https://github.com/tolemac/ToleFocus
[13] react-focus-trap: https://github.com/vigetlabs/react-focus-trap
[14] AUI: https://docs.atlassian.com/aui/
[15] focus-lock: https://github.com/theKashey/focus-lock
[16] dom-focus-lock: https://github.com/theKashey/dom-focus-lock
[17] react-focus-lock: https://github.com/theKashey/react-focus-lock
[18] vue-focus-lock: https://github.com/theKashey/vue-focus-lock
[19] демо: https://codesandbox.io/s/jllj5kr6ov
[20] Одного програмиста из Финляндии: https://habrahabr.ru/post/336600/
[21] Источник: https://habrahabr.ru/post/338130/
Нажмите здесь для печати.