Перейти к основному содержимому

Правила UI Accessibility (A11Y)

Назначение

Документ фиксирует обязательные требования к доступности frontend-приложений Pin. Цель — обеспечить минимум WCAG 2.1 Level AA для всех экранов, поддержку клавиатуры, screen reader и пользователей с ограничениями моторики, зрения и когнитивных способностей.

Целевой стандарт

  • WCAG 2.1 Level AA — минимум.
  • WCAG 2.1 Level AAA — для критичных диалогов (вход, подтверждение деструктивных действий, экспорт).
  • Keyboard-only navigation — приложение полностью используемо без мыши.
  • Screen reader compatibility — VoiceOver (macOS/iOS), NVDA (Windows), TalkBack (Android), JAWS.

Базовые требования

Контрастность

ЭлементКонтраст к фонуСтандарт
Основной текст ≥ 18pt regular4.5:1AA
Крупный текст ≥ 24pt или ≥ 18pt bold3:1AA
UI-компоненты (border, focus ring)3:1AA
Disabled-элементыКонтраст можно снизить, но визуально читаемы

Все цветовые токены валидируются на контрастность через axe-core в pre-commit hook.

Размер шрифта и масштабирование

  • Минимальный размер текста — 14px (десктоп) и 16px (мобильный).
  • Поддержка browser zoom до 200% без потери функциональности.
  • Поддержка native font scaling в системных настройках.

Цвет — не единственный носитель смысла

  • AlertLevel (Green/Yellow/Red/Black) дублируется иконкой и текстовой меткой.
  • Статусы валидации помечаются иконкой + цветом + текстом одновременно.
  • Чарты в светофоре имеют паттерны для дальтоников (полоски/точки).

Клавиатурная навигация

Базовый порядок

ДействиеКлавишаПоведение
Переход вперёдTabПо всем интерактивным элементам в логическом порядке
Переход назадShift+TabОбратный порядок
Активировать кнопку/ссылкуEnter или SpaceКнопки — обе; ссылки — Enter
Закрыть диалог/popoverEscapeВозвращает фокус к триггеру
Открыть command paletteCtrl+K (или Cmd+K)Глобально доступна
Поиск в таблицеCtrl+F (или Cmd+F)Открывает поиск таблицы (override browser default)

Focus management

  • Видимый focus ring обязателен (минимум 3px, контраст 3:1).
  • При открытии модала фокус перемещается на первый интерактивный элемент модала.
  • При закрытии модала фокус возвращается на триггер.
  • Focus trap внутри модала — Tab циклически переключается внутри.
  • Skip-link «Перейти к основному содержимому» в начале каждой страницы.

Shortcuts

Сервисные shortcuts документируются в 04-frontends/pin-admin/07-shared/lib/keyboard-shortcuts.md. Базовый набор:

ShortcutДействие
Ctrl+K / Cmd+KCommand palette
Ctrl+/Помощь / список shortcuts
Ctrl+SСохранить (в формах)
Ctrl+Shift+SСохранить как черновик
Ctrl+EnterSubmit формы
EscapeЗакрыть диалог / отменить inline edit
g jПерейти в Журналы (gmail-style)
g dПерейти в Дашборды
g sПерейти в Расписания

ARIA roles и labels

Базовые роли

ЭлементРольАтрибуты
Header app barrole="banner"
Sidebar navrole="navigation" aria-label="Главная навигация"
Main contentrole="main"
Footerrole="contentinfo"
Modalrole="dialog" aria-modal="true" aria-labelledby="dialog-title"Описание заголовка
Toastrole="status" (info) или role="alert" (error)
Tab listrole="tablist" + role="tab" + role="tabpanel"aria-selected, aria-controls
Sortable columnaria-sort="ascending" / "descending" / "none"

Labels

  • Каждый input имеет связанный label через <label for=""> или aria-labelledby.
  • Иконочные кнопки имеют aria-label.
  • Decorative иконки помечаются aria-hidden="true".
  • Loading spinner имеет role="status" + aria-live="polite" + текст «Загрузка...».

Live regions

Типaria-liveИспользование
Toast infopoliteИнформационные сообщения
Toast errorassertiveОшибки, требующие внимания
Validation errorspoliteПоявление ошибок валидации
Progress updatespoliteПрогресс долгих операций

Формы

  • Каждое поле имеет label, не только placeholder.
  • Required-поля помечаются aria-required="true" и визуально (звёздочка + текст).
  • Ошибка валидации связана с полем через aria-describedby.
  • При submit с ошибками фокус автоматически переходит на первое invalid поле.
  • Сообщения об ошибке — текстовые, не только цветом.
  • Disabled-кнопки имеют aria-disabled="true" и причину disabled через aria-describedby или tooltip.

Таблицы

  • <table> со <thead> и <tbody>.
  • Заголовки колонок — <th scope="col">.
  • Sortable колонки имеют aria-sort + видимый индикатор.
  • Pagination имеет aria-label с текущей страницей.
  • Empty state описан текстом, не только иконкой.
  • Bulk actions описаны через aria-label и доступны с клавиатуры.

Изображения и иконки

  • Декоративные иконки: aria-hidden="true".
  • Иконки с смыслом: aria-label="..." или <span class="sr-only">текст</span> рядом.
  • Изображения с контентом: <img alt="осмысленное описание">.
  • Изображения, дублирующие текст рядом: <img alt="">.

Reduced motion

  • Все анимации >200ms имеют отключение через @media (prefers-reduced-motion: reduce).
  • Карусели/слайдеры не запускаются автоматически.
  • Анимация фокуса должна оставаться (короткая) даже при reduced-motion.

Тестирование A11Y

ИнструментИспользованиеЭтап
eslint-plugin-jsx-a11yLint-проверки на этапе разработкиdev
axe-core через @axe-core/reactRuntime checks в dev режимеdev
Playwright + @axe-core/playwrightE2E A11Y проверкиCI
Storybook + @storybook/addon-a11yComponent-level A11Ydev/CI
Manual screen reader testingVoiceOver / NVDA для критичных flowsrelease
Manual keyboard testingПолный обход без мыши для критичных flowsrelease

Запрещено

  • Использование outline: none без замены на видимый focus ring.
  • tabindex="-1" на интерактивных элементах без причины.
  • tabindex > 0 (нарушает порядок навигации).
  • Использование <div onClick> без role="button" + tabIndex={0} + onKeyDown.
  • Auto-focus в формах без явной необходимости.
  • Auto-redirect/auto-refresh без user control.
  • Использование цвета как единственного индикатора состояния.

Обратные ссылки

Автоссылки: где используется этот документ.

Связанные документы