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

Символ инклюзивного дизайна, вплетенный в структуру, напоминающую цепочку ДНК
Символ инклюзивного дизайна, вплетенный в структуру, напоминающую цепочку ДНК

На первый взгляд создание доступной среды в цифровом продукте кажется простой задачей. В конце концов, что может быть проще, чем использовать нормальные кнопки вместо div? Но когда пытаешься масштабировать такой подход, все становится сложнее. В этой статье я начну с базовых компонентов (текстовые поля, попапы), а затем объясню, как сделать доступной целую платформу из множества разных приложений, которые написаны десятками разных команд.

Что я понимаю под масштабируемостью

Wrike — универсальное решение для управления рабочими процессами. Продукт большой, и наша клиентская база тоже: Wrike используют 21 000 компаний разных размеров. 

Люди из разных отделов работают по разным процессам с помощью разных инструментов. Например, менеджеры используют инструменты для планирования ресурсов и диаграммы Ганта, а дизайнеры — плагины для продуктов Adobe и возможность добавлять комментарии прямо на изображения и другие документы. 

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

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

Приложением должно быть удобно пользоваться на разных платформах (Mac, Windows, iOS, Android). Wrike может работать в браузере как одностраничное веб-приложение, но благодаря Electron может предоставлять пользователям на десктопах опыт близкий к нативному. А еще мы хотим, чтобы интерфейс был доступен людям с постоянной или временной инвалидностью.

Wrike разрабатывают 20+ продуктовых команд в трех странах. У нас в активе уже около двух с половиной миллионов строк кода и более 200 репозиториев. Основное требование к доступности — она должна масштабироваться среди всех наших команд. 

Как мы этого добиваемся? Как измеряем прогресс?

Начнем с основ

Для создания веб-страницы требуется:

  • Контент (очевидно);

  • Некоторое количество HTML;

  • CSS;

  • JS.

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

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

Для проверки можно запустить Lighthouse или другой похожий инструмент и сразу получить автоматически сгенерированный отчет — базовый аудит доступности:

Пример отчета в Lighthouse. На отчете выводится плашка с оценкой 92. Отмечены проблемы с использованием ARIA-атрибутов и контрастом между цветом текста и цветом фона
Пример отчета в Lighthouse. На отчете выводится плашка с оценкой 92. Отмечены проблемы с использованием ARIA-атрибутов и контрастом между цветом текста и цветом фона

Предположим, аудит показывает оценку 92 на странице, написанной на чистом HTML. Что это число говорит о странице? И как поддерживать этот уровень по мере того, как приложение становится все более и более сложным?

Apps in the wild

Два браузерных окна: окно слева (single-page application) содержит три шаблона, переключаться между которыми приложение может без перезагрузки страницы; окно справа (обычный веб-сайт) также содержит три страницы, переход между ними сопровождается полной перезагрузкой. Изображение © digitalclaritygroup.com
Два браузерных окна: окно слева (single-page application) содержит три шаблона, переключаться между которыми приложение может без перезагрузки страницы; окно справа (обычный веб-сайт) также содержит три страницы, переход между ними сопровождается полной перезагрузкой. Изображение © digitalclaritygroup.com

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

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

При создании компонента важно следить, чтобы способ взаимодействия пользователя с этим компонентом оставался предсказуемым вне зависимости от того, делает он это при помощи мыши, кнопками на клавиатуре или через интерфейс скринридера. Возьмем обычный выпадающий список (<select>): логично, что стрелка вверх перемещает выделение вверх, стрелка вниз перемещает выделение вниз, Enter подтверждает выбор, и курсором мыши можно делать все то же самое. А что если компонент позволяет искать с помощью ввода текста, имеет функцию автодополнения, а также содержит дополнительные контролы для каждого элемента в списке результатов? Неправильно спроектированная навигация превратит работу с компонентом в кошмар, и автоматические проверки от его наступления не спасут.

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

Управление фокусом — отдельная большая тема, на которой я не стану подробно останавливаться в этой статье, но приведу несколько примеров задач, которые приходится решать. Например, куда по умолчанию должен встать клавиатурный фокус, когда открывается диалоговое окно? Должен ли фокус быть строго ограничен областью диалога или нужно давать пользователю возможность выйти Tab’ом в интерфейс самого браузера? Вопросов много, и простых ответов зачастую нет (WCAG, конечно, помогает, но далеко не всегда).

Разработчики — люди с разным опытом и специализацией. Доступность — не единственная проблема, которую приходится решать при создании очередного приложения. Есть также вопросы безопасности, производительности и т. д. Как бы ни менялся продукт, интерфейс должен работать предсказуемо, выглядеть консистентно в рамках продукта, а API компонентов — быть понятным.

Со всем этим может помочь дизайн-система.

Дизайн-система: почему иногда ее недостаточно

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

Макеты наших компонентов, например, выглядят так:

Скриншот интерфейса Figma (инструмент прототипирования) с различными состояниями пикера (комбинации текстового поля со списком результатов) в темной и светлой теме
Скриншот интерфейса Figma (инструмент прототипирования) с различными состояниями пикера (комбинации текстового поля со списком результатов) в темной и светлой теме

По сути это просто набор визуальных состояний в Figma. Разработчик смотрит на картинку и может себе представить, как элемент интерфейса выглядит в реальном приложении в тот или иной момент. Дизайнер и разработчик могут заранее обсудить, как что должно работать, найти проблемы и протестировать решение на небольшом прототипе. У каждого визуального компонента есть брат-близнец в библиотеке компонентов (у нас их две: одна на Angular для нашего легаси-стека, другая для React).

Но если в компании уже есть дизайн-система, имеет смысл спросить: действительно ли вы ее используете?

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

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

Мы делаем то, что делает каждая продуктовая компания: собираем аналитику и прочую обратную связь, пытаемся отследить проблемы и недостатки продукта. Например, мы собираем из кода всех приложений в продукте ссылки на используемые компоненты, чтобы понять, какая часть из них переиспользуемые, а какие собраны по месту на голом HTML/JSX. Нормальное соотношение для несложной вьюхи — примерно 40/60, для сильно специфичных может быть ниже. У нас есть отчеты, которые показывают динамику.

Отчет об использовании дизайн-системы; В данном случае отчет о функции канбан-доски перечисляет, сколько компонентов из общей библиотеки используются (12) и каково их процентное соотношение в шаблонах (38%), список этих компонентов и их относительная сложность
Отчет об использовании дизайн-системы; В данном случае отчет о функции канбан-доски перечисляет, сколько компонентов из общей библиотеки используются (12) и каково их процентное соотношение в шаблонах (38%), список этих компонентов и их относительная сложность

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

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

Например, контекстное меню:

Заголовок меню "Show on board" с единственным пунктом "Tasks from subfolders", линия-разделитель, под ней текст "Only [account admins] can edit workflows", [account admins] — ссылка на раздел документации
Заголовок меню "Show on board" с единственным пунктом "Tasks from subfolders", линия-разделитель, под ней текст "Only [account admins] can edit workflows", [account admins] — ссылка на раздел документации

Меню открывается нажатием на кнопку с тремя точками. Панель с тенью содержит пункты меню и текстовую карточку со ссылкой. С точки зрения дизайн-системы все согласовано: всплывающая панель, заголовок раздела, пункты меню, текст со ссылками, дизайн-токены для типографики, цветов и отступов используются правильно. Вот только как на самом деле должна работать ссылка внизу для пользователей клавиатуры или скринридера? Неясно.

Вероятно, мы можем добавить ее в список элементов меню, по которым можно перемещаться с помощью клавиш со стрелками вверх-вниз. Другой вариант — добавить ее как отдельную позицию в tab order. Предположим, какое-то решение на стороне фронтенда мы найдем, но лучше задать вопросы: допустимо ли в принципе иметь подобную ​​ссылку в контекстном меню? Должны ли мы договориться с командой дизайнеров о том, что они должны или не должны использовать в рамках определенного паттерна?

Другой пример — списки:

Заголовок «Projects and folders», под ним древовидный список:

Talks,
внутри Talks:
> Back-end,
> Front-end,
> Future,

Пункт "Talks" отмечен фокусным кольцом, открытое поддерево отмечено стрелкой вниз
Заголовок «Projects and folders», под ним древовидный список: Talks, внутри Talks: > Back-end, > Front-end, > Future, Пункт "Talks" отмечен фокусным кольцом, открытое поддерево отмечено стрелкой вниз

Wrike — продукт, основанный на пространствах с древовидной иерархией папок, проектов и задач внутри. Нам нужен какой-то паттерн навигации в дереве, потому что оно может быть очень длинным. Мы не хотим, чтобы пользователи «табали» сотни папок каждый раз, когда им нужно перейти к следующей области интерфейса.

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

Подобных оповещений может быть тоже очень много:

Окно «Входящие» с заголовком Sep 2 (2 сентября) и несколькими уведомлениями, одно из них отмечено фокусным кольцом
Окно «Входящие» с заголовком Sep 2 (2 сентября) и несколькими уведомлениями, одно из них отмечено фокусным кольцом

И третья область — канбан-доска, в которой каждая колонка — это примерно такой же список:

На доске две колонки ("In progress" and "Completed"), в первой колонке две задачи, во второй колонке одна задача
На доске две колонки ("In progress" and "Completed"), в первой колонке две задачи, во второй колонке одна задача

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

Мы обнаружили, что лучше, когда дизайн-система содержит не только визуальный слой, но и слой интерактивных паттернов, и уже отдельно – собранные готовые компоненты.

Если вы хотите углубиться в эту тему, рекомендую взглянуть на дизайн-систему Adobe — Spectrum. Есть и другие примеры, но система Adobe хороша тем, что ее реализация на React имеет несколько слоев:

  • Абстрактный слой (@react-stately), который определяет, например, общий API работы со списками, деревьями и таблицами.

  • Слой браузера (@react-aria), который работает с ARIA-атрибутами и обработкой событий и реализует поведение с клавиатуры и скринридеров для большинства часто используемых в вебе паттернов.

  • Готовые компоненты (@react-spectrum), отвечающие бренду компании, которые можно подключить и сразу использовать в приложении.

Как автоматизация помогает сделать продукт доступным

Существует предубеждение, что автоматизация никак не помогает обеспечению доступности. Почему? Ну, невозможно имитировать поведение человека и тем более сложно автоматизировать тестирование с помощью программ экранного доступа — одну из самых сложных частей тестирования доступности в целом.

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

Согласно отчету Automated Accessibility Coverage Report от Deque Systems, 57,38% от общего числа проблем с доступностью обнаруживаются с помощью автоматизированных тестов. Автоматизация и дизайн-система могут идти рука об руку.

Что можно сделать, чтобы более эффективно использовать эту комбинацию: 

  • Использовать Storybook. Если у вас уже есть дизайн-система, у вас наверняка есть и демо-страницы. Тестировать компоненты в разных состояниях там проще, чем в продакшене.

  • Строго следовать правилам линтинга, чтобы избежать распространенных ошибок в разметке (например, подключить ESLint-плагин jsx-a11y).

  • После ручного аудита в Lighthouse или axe DevTools стоит написать автоматизированные тесты (например, с помощью axe-Selenium).

Болезни роста

Решают ли советы выше все возможные проблемы? Думаю, нет. Самая сложная из всех, с которыми мы столкнулись, — рост. По мере роста команд и усложнения продукта и бизнеса в целом возникает немало хаоса.

Вот лишь некоторые проблемы, с которыми мы столкнулись в Wrike:

  • Централизованные (авторитарные) подходы (например, «Все визуальные компоненты должны создаваться или проверяться внутренней командой UI Kit») перестают работать, командам нужна реальная независимость.

  • Технологии и автоматизация не решают организационные вопросы. Если никто не знает, как подступиться к устаревшему приложению или компоненту, или вообще не хочет что-либо делать с ним, потому что это не принесет дохода, технологии не помогут.

  • Интуиция — это не метрика для определения качества, а без метрик качество не масштабируется. В большой компании трудно понять, на каком этапе большого пути находится та или иная команда или часть продукта.

Я думаю, что нужно уделять внимание не только дизайну и коду, но и культуре. Работа с людьми — это тоже своего рода набор паттернов или фреймворков, которыми нужно уметь пользоваться. Важно наладить связи между людьми с разными мнениями и разными взглядами на мир.

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

Вот некоторые из них:

  • Просим ли мы обратную связь от людей с инвалидностью?

  • Есть ли у нас отдельная команда, которая отвечает за доступность? Если нет, то планируем ли кого-то нанять в существующие команды или запустить обучение?

  • Сотрудничают ли наши дизайнеры и инженеры в этой области, или последние получают готовые макеты и делают интерфейс по ним, не задавая вопросов?

  • Входит ли доступность в каком-либо виде в наши ежеквартальные цели?

На эти вопросы можно получить ответ: «Мы этого не делаем, потому что у нас нет таких клиентов». Но это Уловка-22 — задача, в которой решение изначально невозможно из-за формулировки проблемы.

Вы не делаете контент доступным, потому что у вас нет таких (каких, кстати?) клиентов. А таких клиентов нет потому, что вы не делаете контент доступным.

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

Что нужно сделать, чтобы начать путь к доступности

Обозначьте свою позицию. Есть несколько способов: разместить заявление на сайте компании или рассказывать об этом клиентам, в конце концов — сделать доклад на внутренней конференции или опубликовать статью на Хабре :) Важно, чтобы послание было прозрачным и дошло до всех в компании. Доступность нельзя масштабировать, если она не будет заложена в ДНК компании, а будет уделом энтузиастов с горящими глазами, ресурс горения которых может быстро закончиться.

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

Обеспечьте сотрудникам возможность получить опыт и обучиться. Попробуйте внести небольшие изменения в определенные компоненты дизайн-системы или какую-то новую область продукта, прежде чем масштабировать подход на всех. Для роста людям нужна определенность, поощрение инициативы и положительная обратная связь. Если постоянно говорить инженерам и дизайнерам, что доступность продукта хромает и при этом требовать мгновенных изменений, это никого в команде не замотивирует — люди просто выгорят.

Зовите для тестирования реальных людей и оценивайте с ними ваш прогресс. Например, можно создать небольшое сообщество пользователей с инвалидностью (поверьте, вы быстро их найдете, если просто спросите в блоге) и старайтесь регулярно с ними общаться, чтобы понимать, насколько далеко вы продвинулись.

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

Признайте, что вы находитесь на пути, который займет время. Если мы говорим о продукте, который был запущен в середине 2000-х годов, путь к полной доступности может занять годы. Но со временем все наладится, и оно того стоит!

Советы для команд, которые хотят делать доступный продукт

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

Если есть возможность собрать интерактивный прототип — еще лучше. Можно протестировать его внутри команды и даже на реальных пользователях до начала полномасштабной разработки. Подход «доделаем потом» тоже может сработать, но обойдется гораздо дороже. Сложно исправить компонент, который изначально не был рассчитан на пользователей клавиатуры или скринридеры, и одновременно не нарушить опыт, который вы уже проработали для мыши или тачскрина.

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

Не бойтесь неудач. Некоторые вещи невозможно исправить с первой попытки. Продолжайте пробовать и не бойтесь сказать, что что-то идет не так. Возможно, даже придется переделывать некоторые части продукта с нуля. Важно помнить, что работа над доступным приложением — это марафон, а не спринт.

Подводя итог

Доступность — это не просто тренд, оценка в Lighthouse, требования ГОСТ или спецификации ARIA и WCAG. Важно сосредоточиться на кросс-функциональном подходе и людях, а не только на стандартах написания кода.

Если хотите узнать о том, как создавать доступные компоненты, рекомендую прочитать A Complete Guide To Accessible Front-End Components журнала Smashing Magazine. 

Буду рад ответить на вопросы и комментарии!

Комментарии (0)