Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Путешествие в страну доступности

Путешествие в страну доступности

Yaroslav Losev

December 11, 2023
Tweet

More Decks by Yaroslav Losev

Other Decks in Programming

Transcript

  1. An accessible site is one whose content can be accessed

    regardless of any user's impairments – web.dev
  2. Спектр проблем Зрение • слабовидящие • незрячие • дальтоники Слух

    • глухие • слабослышащие • нарушения речи Моторика • тремор • паралич • нет конечностей Когнитивные • дислексия • СДВГ • эпилепсия Ситуативные • блики • заняты руки • переломы
  3. 51% Имеет хотя бы одну настройку доступности Используют увеличенный шрифт

    35% Используют скринридер 0.02% Настройки доступности https://inclusion.yandex.ru/settingsresearch
  4. Perceivable Семантическая структура Контент представлен не только графически 02 Цвет

    и контраст 03 Масштабируемость 04 Подписи и лейблы 05 01
  5. Operable Навигация не только мышью Порядок фокуса 02 Нет ярких

    вспышек 03 Пользователь успевает взаимодействовать с интерфейсом 04 01
  6. Не думать про доступность Ждать, что команда инклюзия все исправит

    Обратиться к инклюзии и исправить командой сервиса
  7. Аудит доступности Определение пользовательских сценариев 02 Аудит (зрячий + незрячий)

    03 Отчёт 04 Работа над ошибками 05 Формируется перечень сервисов и окружений 01
  8. Какие есть опции «Набегами» • Неконсистентно между итерациями • Потенциально

    дорого • Всегда найдется, чем заняться кроме a11y Непрерывно • В идеале — рабочий продукт в любой точке • Модифицируются процессы • Доступность становится частью культуры (например, как мобильный адаптив) • Многие команды Яндекса идут по этому пути
  9. Пример непрерывного флоу • На этапе планирования фичи менеджер думает

    про необходимость доступности (не все сценарии требуют этого) • Менеджер подсвечивает необходимость и серые зоны • RFC как сделать фичу доступной • Дизайн-ревью (разработчик проверяет в том числе и доступность) • Разработка • Ручное тестирование, тестирование асессорами (?), автоматическое тестирование
  10. Как сделать приложение доступным? Семантические элементы • header, footer, h1…

    • button, a, input, textarea… • dialog, popover ARIA-атрибуты • role=“heading”, aria-level=“1" • aria-pressed, aria-labbeledby • role=“dialog”, aria-hidden, inert
  11. Пара интересных правил • anchor-has-content; anchor-is-valid • control-has-associated-label • alt-text;

    img-redundant-alt • interactive-supports-focus; no-noninteractive-element-interactions • no-static-element-interactions
  12. Что сделали мы? Сконфигурировали линтер и мапинги 02 Включили на

    уровень warning 03 Часть подняли до error, завели задачи для остальных 04 Выбрали актуальные для нас правила 01
  13. ESLint 01 03 02 04 Статически проверили код React и

    отловили часть ошибок Пропустили часть человеческих ошибок Указали обязательные атрибуты Не проверили страницу целиком
  14. Основное • Конфигурируемые правила: WCAG A / AA, best practices,

    … • «With axe-core, you can find on average 57% of WCAG issues automatically» • Есть официальная подвязка к React, WebDriver, Pupeteer • Browsers: Edge 40+ , Chrome 42+ , Firefox 38+ , Safari 7+ • Open Source
  15. console.log(results.violations) • html-has-lang: Ensures every HTML document has a lang

    attribute • landmark-one-main: Ensures the document has a main landmark • page-has-heading-one: Ensure that the page, or at least one of its frames contains a level-one heading • region: Ensures all page content is contained by landmarks
  16. 01 03 02 04 axe-core Проверили страницу Интегрируется с любимыми

    тестами Отловили часть интеграционных ошибок Не поймали часть ошибок
  17. Tabs Pattern Tabs Pattern: 1. Tab 2. Left/Right Arrow 3.

    Space/Enter 4. Home/End * 5. Delete * 6. Shift + F10 *
  18. С какими проблемами столкнулись? Существующие библиотеки слишком специфичны 02 Большая

    вариативность требований 03 Разное поведение даже стандартных элементов в браузерах 01 • Разные браузеры, устройства, способы взаимодействия • Специфика LTR, RTL, i18n
  19. react-aria Берет на себя ответственность только за поведение, но не

    за отображение 02 Мышь, клавиатура, тач, скрин ридеры 03 WAI - ARIA 04 Представляет набор хуков для основных примитивов 01
  20. Примитивы для событий • useFocus • useFocusVisible • useFocusWithin •

    useHover • useKeyboard • useLongPress • useMove • usePress • useFocusRing • useClipboard https://react-spectrum.adobe.com/react-aria/getting-started.html
  21. Контролы • useButton • useCheckbox • useTextField • useBreadcrumbs •

    useMenu • useTabList • useModal • usePreventScroll • useSelect • useRangeCalendar https://react-spectrum.adobe.com/react-aria/getting-started.html
  22. <div className={cx.button} onClick={props.onClick} role="button" tabIndex={0} onKeyDown={props.onClick} > {props.text} </div> import

    {useButton} from "@react-aria/button"; … const ref = useRef<HTMLDivElement>(null); const { buttonProps } = useButton( { ...props, onPress, elementType: 'div', }, ref, ); … return ( <div ref={ref} className={cx.button} {…buttonProps}> {props.text} </div> ); Button.tsx
  23. import {useButton} from "@react-aria/button"; … const ref = useRef<HTMLDivElement>(null); const

    { buttonProps } = useButton( { ...props, onPress, elementType: 'div', }, ref, ); … return ( <div ref={ref} className={cx.button} {…buttonProps}> {props.text} </div> ); <div … role="button" tabindex="0"> Sign in </div> Button.tsx
  24. const TextField: React.FC<ITextFieldProps> = (props) => { const ref =

    useRef<HTMLInputElement>(null); const validationState = props.hasError ? 'invalid' : 'valid'; const { labelProps, inputProps } = useTextField({ ...props, validationState }, ref); return ( <div className={props.className}> <Label {...labelProps} htmlFor={labelProps.htmlFor} text={props.label} /> <Input {...inputProps} ref={ref} hasError={props.hasError} /> </div> ); }; TextField.tsx
  25. <div …> <label … for="react-aria5217437109-1" id="react-aria5217437109-2" > Login </label> <input

    … id="react-aria5217437109-1" type="text" aria-labelledby="react-aria5217437109-2" value="" /> </div> TextField.tsx
  26. Дальнейшие планы Перевезти основные компоненты на react-aria 02 Внедрить E2E

    тестирование доступности 03 Правила ESLint должны стать обязательными 04 Пропагандировать культуру доступности в команде 01