Хук useModal предназначен для управления модальными
окнами с соблюдением стандартов доступности (accessibility, a11y). Он
обеспечивает правильное взаимодействие с фокусом, экранными ридерами и
навигацией с клавиатуры. Основная задача — создать область интерфейса,
которая блокирует фокус вне модального окна и корректно
оповещает технологии доступности о появлении нового интерактивного
контента.
import { useModal } from '@react-aria/overlays';
import { useOverlay } from '@react-aria/overlays';
import { useDialog } from '@react-aria/dialog';
useModal часто применяется совместно с
useOverlay и useDialog. Основная комбинация
выглядит так:
function Modal({ isOpen, onClose, children }) {
let ref = useRef();
let { modalProps } = useModal();
let { overlayProps } = useOverlay({ isOpen, onClose, isDismissable: true }, ref);
let { dialogProps } = useDialog({}, ref);
if (!isOpen) return null;
return (
{children}
);
}
Здесь ключевые моменты:
modalProps — добавляет атрибуты для
блокировки фокуса вне модального окна.overlayProps — управляет показом и
скрытием окна, поддерживает закрытие по клику вне модального
контента.dialogProps — включает правильные
ARIA-атрибуты (role="dialog",
aria-modal="true") для экранных ридеров.Главная задача useModal — удерживать фокус внутри
модального окна. Это реализуется через:
Пример:
import { FocusScope } from '@react-aria/focus';
function ModalContent({ children }) {
return (
{children}
);
}
contain — блокирует фокус внутри
модального окна.restoreFocus — возвращает фокус к
исходному элементу при закрытии.autoFocus — автоматически фокусирует
первый интерактивный элемент.useOverlay предоставляет механизмы для:
isDismissable: true).shouldCloseOnEsc по
умолчанию true).let { overlayProps } = useOverlay({ isOpen, onClose, isDismissable: true }, ref);
В сочетании с useModal это обеспечивает
полностью управляемый интерактивный опыт,
соответствующий стандартам WCAG.
Для плавного появления и исчезновения модальных окон можно
комбинировать useModal с CSS-анимациями или библиотекой
react-transition-group. Важно не прерывать
фокусировку при анимации, чтобы пользовательский опыт оставался
корректным:
import { CSSTransition } from 'react-transition-group';
...
useModal корректно работает с вложенными оверлеями.
Каждый новый модальный уровень:
aria-hidden, скрывая элементы вне текущей модалки
от экранных ридеров.FocusScope для
управления фокусом.aria-labelledby и
aria-describedby для информирования пользователя о
содержимом окна.useModalfunction AppModal({ isOpen, onClose, title, children }) {
let ref = useRef();
let { modalProps } = useModal();
let { overlayProps } = useOverlay({ isOpen, onClose, isDismissable: true }, ref);
let { dialogProps } = useDialog({ 'aria-label': title }, ref);
if (!isOpen) return null;
return (
{title}
{children}
);
}
Такое сочетание обеспечивает полностью доступное и управляемое модальное окно, соответствующее стандартам ARIA и лучшим практикам React.