useDescription для описаний

Хук useDescription предназначен для управления описаниями компонентов интерфейса в соответствии со стандартами доступности (ARIA). Он используется для добавления вспомогательного текста, который будет озвучиваться скринридерами, но не обязательно отображается визуально. Основная задача — обеспечить контекст для элементов, таких как кнопки, поля ввода, слайдеры и другие интерактивные компоненты.


Основная концепция

useDescription возвращает атрибуты, которые следует передать HTML-элементу, выступающему как описание. В типичной реализации это id, который используется с aria-describedby. Хук обеспечивает:

  • Автоматическое создание уникального идентификатора для описания.
  • Объединение нескольких описаний при необходимости.
  • Поддержку скрытых описаний, которые остаются доступными для скринридеров.

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

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

function FieldDescription({ children }) {
  const { descriptionProps } = useDescription();
  
  return (
    <div {...descriptionProps}>
      {children}
    </div>
  );
}

В этом примере descriptionProps содержит id, который можно передать в aria-describedby основного интерактивного элемента.


Связь с другими ARIA-хуками

useDescription часто используется вместе с хуками вроде useTextField, useButton или useSlider. В этих случаях он добавляет дополнительный контекст к элементу без вмешательства в визуальное представление.

Пример интеграции с useTextField:

import { useTextField } from "@react-aria/textfield";
import { useDescription } from "@react-aria/utils";

function TextInput({ label, description }) {
  const { descriptionProps } = useDescription(description);
  const { labelProps, inputProps } = useTextField({ label }, null);

  return (
    <div>
      <label {...labelProps}>{label}</label>
      <input {...inputProps} aria-describedby={descriptionProps.id} />
      <div {...descriptionProps}>{description}</div>
    </div>
  );
}

Здесь aria-describedby связывает поле ввода с описанием, гарантируя, что скринридеры прочитают текст описания после имени поля.


Параметры и возвращаемые значения

Параметры:

  • children — текст или JSX, который выступает описанием. Может быть пустым, если описание не требуется.

Возвращаемые значения:

  • descriptionProps — объект с атрибутами для HTML-элемента описания. Основной атрибут — id.

Пример с динамическим описанием:

import { useDescription } from "@react-aria/utils";
import { useState } from "react";

function DynamicDescription() {
  const [error, setError] = useState("");
  const { descriptionProps } = useDescription(error);

  return (
    <div>
      <input type="text" onB lur={e => setError(e.target.value ? "" : "Поле обязательно для заполнения")} />
      <div {...descriptionProps}>{error}</div>
    </div>
  );
}

В этом примере описание меняется в зависимости от состояния валидации. Скринридер будет озвучивать актуальный текст.


Работа с несколькими описаниями

Если необходимо добавить несколько описаний к одному элементу, useDescription автоматически объединяет идентификаторы, чтобы передать их через aria-describedby.

const { descriptionProps: desc1Props } = useDescription("Описание 1");
const { descriptionProps: desc2Props } = useDescription("Описание 2");

<input aria-describedby={`${desc1Props.id} ${desc2Props.id}`} />
<div {...desc1Props}>Описание 1</div>
<div {...desc2Props}>Описание 2</div>

Скринридер прочитает оба текста последовательно, обеспечивая полный контекст.


Скрытые описания

React Aria поддерживает скрытые описания для случаев, когда текст нужен только для скринридеров. Обычно это достигается с помощью CSS-класса:

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  border: 0;
}

Применение:

<div {...descriptionProps} className="sr-only">{description}</div>

Элемент не виден на экране, но полностью доступен для технологий чтения с экрана.


Практические рекомендации

  • Использовать для вспомогательного контента: useDescription не заменяет aria-label или label, а дополняет их.
  • Соблюдать уникальность id: Хук автоматически генерирует идентификаторы, но при ручной передаче нескольких описаний нужно убедиться в отсутствии конфликтов.
  • Интеграция с динамическими состояниями: Поддержка изменений текста в реальном времени важна для форм с валидацией, сообщений об ошибках и уведомлений.

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

  • useDescription связывает текст с элементом через aria-describedby.
  • Позволяет динамически управлять описаниями и их видимостью.
  • Работает с любыми интерактивными элементами, улучшая доступность.
  • Поддерживает множественные описания и скрытые элементы для скринридеров.

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