useDialog — это хук из библиотеки React
Aria, предназначенный для управления доступностью диалоговых
окон (модальных окон) в приложениях на React. Он обеспечивает корректную
работу с экранными читалками и клавиатурной навигацией, автоматически
добавляя необходимые ARIA-атрибуты и управление фокусом. Хук не
предоставляет визуальную часть компонента, он отвечает только за
поведение и доступность.
Простейший вызов хука выглядит так:
import { useDialog } from '@react-aria/dialog';
import { useOverlay } from '@react-aria/overlays';
import { useRef } from 'react';
function Modal({ title, isOpen, onClose, children }) {
let ref = useRef();
let { dialogProps, titleProps } = useDialog({ role: 'dialog', 'aria-label': title }, ref);
if (!isOpen) return null;
return (
<div {...dialogProps} ref={ref}>
<h2 {...titleProps}>{title}</h2>
{children}
<button onCl ick={onClose}>Закрыть</button>
</div>
);
}
В этом примере useDialog возвращает объект
dialogProps для контейнера диалога и
titleProps для заголовка. Эти свойства включают все
необходимые атрибуты ARIA и управление фокусом для доступности.
Хук принимает два аргумента: объект с опциями и ref на
элемент диалога.
Основные опции:
role — роль диалога, чаще всего 'dialog'
или 'alertdialog'. 'alertdialog' используется
для критических сообщений, требующих немедленного внимания
пользователя.'aria-label' или 'aria-labelledby' — для
заголовка диалога. Можно использовать один из двух способов, но
aria-labelledby предпочтительнее, если заголовок
представлен отдельным элементом.isDismissable — булевое значение. Если
true, диалог можно закрыть кликом вне его области или
клавишей Escape.onClose — функция, вызываемая при закрытии
диалога.UNSAFE_style и UNSAFE_className —
позволяют задать стили и классы, но их использование не влияет на
доступность.Одним из ключевых преимуществ useDialog является
управление фокусом при открытии и закрытии модального окна. При
открытии:
Для интеграции с overlay-логикой, например, при
затемнении фона или блокировке прокрутки, рекомендуется использовать
useOverlay:
import { useOverlay } from '@react-aria/overlays';
let { overlayProps } = useOverlay({ isOpen, onClose, isDismissable: true }, ref);
overlayProps добавляются к контейнеру, чтобы обеспечить
закрытие по Escape или клику вне модального окна.
useDialog автоматически поддерживает следующие
сценарии:
isDismissable = true.Эта функциональность гарантирует, что диалог будет полностью доступен для пользователей, работающих только с клавиатурой.
Правильная роль диалога критична для доступности:
role="dialog" — стандартный диалог, не
требует немедленного внимания.role="alertdialog" — важное сообщение,
требующее подтверждения. Важно, что экранные читалки автоматически
объявляют его содержание сразу после открытия.Заголовок должен быть связан с диалогом через
aria-labelledby:
<h2 id="dialog-title">{title}</h2>
<div {...dialogProps} aria-labelledby="dialog-title" ref={ref}>
...
</div>
Для полнофункциональных модальных окон рекомендуется комбинировать
useDialog с useOverlay:
import { useOverlay, OverlayProvider } from '@react-aria/overlays';
function Modal({ isOpen, onClose, children }) {
let ref = useRef();
let { overlayProps } = useOverlay({ isOpen, onClose, isDismissable: true }, ref);
let { dialogProps, titleProps } = useDialog({ role: 'dialog', 'aria-label': 'Модальное окно' }, ref);
if (!isOpen) return null;
return (
<div {...overlayProps}>
<div {...dialogProps} ref={ref}>
<h2 {...titleProps}>Заголовок</h2>
{children}
</div>
</div>
);
}
Использование OverlayProvider позволяет корректно
управлять несколькими модальными окнами и приоритетами фокуса в сложных
интерфейсах.
Если содержимое диалога генерируется динамически, важно, чтобы все
фокусируемые элементы были доступны сразу после рендера. React Aria
автоматически обеспечивает корректную работу focus trap и анонсирование
экранными читалками, даже если элементы появляются с задержкой через
useEffect или загрузку данных.
aria-label или
aria-labelledby для улучшения доступности.isDismissable = true, чтобы пользователи
могли закрыть диалог легко.useDialog с useOverlay, если
требуется блокировка фона или управление несколькими модальными
окнами.role="alertdialog"
и выделять их визуально.useDialog в связке с useOverlay
обеспечивает полный контроль над диалогами с соблюдением всех стандартов
доступности, позволяя создавать сложные и удобные интерфейсы без
необходимости вручную прописывать ARIA-атрибуты и логику фокуса.