Описания и подсказки

В библиотеке React Aria управление доступностью компонентов строится на использовании семантических атрибутов ARIA и хуков, предоставляемых библиотекой. Одним из ключевых аспектов является создание описаний и подсказок для элементов интерфейса, чтобы обеспечить корректное взаимодействие для пользователей с ассистивными технологиями.

React Aria предоставляет хуки useTooltip, useDescription и useLabel, которые позволяют добавлять семантические описания и подсказки к элементам без прямого вмешательства в DOM.


Хук useDescription

Хук useDescription используется для добавления описаний к элементам. Он возвращает объект с атрибутом aria-describedby, который можно применить к любому элементу.

Пример использования:

import {useDescription} from '@react-aria/utils';
import {useRef} from 'react';

function TextInputWithDescription() {
  const inputRef = useRef();
  const {descriptionProps} = useDescription({id: 'input-desc'});
  
  return (
    <div>
      <input ref={inputRef} aria-describedby="input-desc" />
      <div id="input-desc" {...descriptionProps}>
        Введите текст, который будет использоваться для поиска.
      </div>
    </div>
  );
}

Ключевые моменты:

  • aria-describedby связывает элемент с его описанием.
  • id описания должен быть уникальным на странице.
  • Этот подход гарантирует, что экранные читалки смогут правильно прочитать описание при фокусе на элементе.

Хук useTooltip

Для реализации подсказок используется хук useTooltip. Он работает в связке с хуком useTooltipTrigger, который управляет состоянием отображения подсказки.

Пример:

import {useTooltip, useTooltipTrigger} from '@react-aria/tooltip';
import {useRef} from 'react';

function ButtonWithTooltip() {
  const buttonRef = useRef();
  const tooltipRef = useRef();
  const {tooltipProps} = useTooltip({id: 'tooltip-1'}, tooltipRef);
  const {triggerProps, tooltipTriggerProps} = useTooltipTrigger({placement: 'top'}, buttonRef);

  return (
    <div>
      <button {...triggerProps} {...tooltipTriggerProps} ref={buttonRef}>
        Наведи на меня
      </button>
      <div {...tooltipProps} ref={tooltipRef} role="tooltip" id="tooltip-1">
        Подсказка: кнопка выполняет действие отправки.
      </div>
    </div>
  );
}

Особенности:

  • role="tooltip" обязательна для правильного распознавания подсказки экранными читалками.
  • Хук useTooltipTrigger управляет показом/скрытием подсказки на события hover, focus и press.
  • Связка tooltipProps и tooltipTriggerProps обеспечивает синхронизацию состояния.

Использование useLabel для описательных элементов

Хук useLabel отвечает за создание связки между элементом управления и его видимой меткой. Он автоматически добавляет aria-labelledby и обрабатывает идентификаторы, что позволяет избежать конфликтов в сложных интерфейсах.

Пример:

import {useLabel} from '@react-aria/label';
import {useRef} from 'react';

function CheckboxWithLabel() {
  const inputRef = useRef();
  const {labelProps, fieldProps} = useLabel({label: 'Согласие с условиями'}, inputRef);

  return (
    <div>
      <input type="checkbox" ref={inputRef} {...fieldProps} />
      <label {...labelProps}>Согласие с условиями</label>
    </div>
  );
}

Преимущества:

  • Обеспечивает корректное связывание элементов для ассистивных технологий.
  • Поддерживает динамические и условные метки без нарушения семантики.

Комплексное использование описаний и подсказок

Часто требуется комбинировать описания и подсказки, чтобы создать более доступный интерфейс. React Aria позволяет это делать, связывая несколько атрибутов ARIA:

import {useDescription, useLabel, useTooltip, useTooltipTrigger} from '@react-aria/utils';
import {useRef} from 'react';

function InputWithTooltipAndDescription() {
  const inputRef = useRef();
  const tooltipRef = useRef();
  
  const {descriptionProps} = useDescription({id: 'desc-1'});
  const {labelProps, fieldProps} = useLabel({label: 'Имя пользователя'}, inputRef);
  const {tooltipProps} = useTooltip({id: 'tooltip-2'}, tooltipRef);
  const {triggerProps, tooltipTriggerProps} = useTooltipTrigger({placement: 'right'}, inputRef);

  return (
    <div>
      <input 
        ref={inputRef} 
        {...fieldProps} 
        aria-describedby="desc-1 tooltip-2" 
        {...triggerProps} 
        {...tooltipTriggerProps} 
      />
      <label {...labelProps}>Имя пользователя</label>
      <div id="desc-1" {...descriptionProps}>
        Поле обязательно для заполнения.
      </div>
      <div {...tooltipProps} ref={tooltipRef} role="tooltip" id="tooltip-2">
        Подсказка: используйте реальные имя и фамилию.
      </div>
    </div>
  );
}

Принципы:

  • aria-describedby может включать несколько идентификаторов, разделённых пробелами.
  • Сочетание useDescription и useTooltip позволяет управлять статическим и динамическим контентом описаний.
  • Хуки React Aria автоматически решают вопросы уникальности id и синхронизации состояний.

Важные рекомендации

  • Всегда использовать семантические роли и ARIA-атрибуты вместе с хуками React Aria.
  • Подсказки должны предоставлять краткую и полезную информацию, не дублируя текст метки.
  • Описания предназначены для дополнительных деталей, которые помогают понять контекст элемента.
  • Проверка доступности через экранные читалки и инструменты автоматической валидации обязательна для сложных интерфейсов.

Эффективное сочетание хуков useLabel, useDescription и useTooltip обеспечивает корректное взаимодействие интерфейса с ассистивными технологиями, улучшая доступность и пользовательский опыт.