React Aria предоставляет мощные инструменты для работы с
доступностью (accessibility) компонентов в React-приложениях. Одним из
ключевых элементов для управления модальными окнами является
ModalProvider. Он используется для координации поведения
всех модальных элементов и обеспечения корректного взаимодействия с
пользователем, включая фокус и клавиатурную навигацию.
ModalProvider и его
рольModalProvider создаёт контекст, который обеспечивает
глобальное управление состоянием модальных окон в приложении. Основные
функции включают:
Пример базовой обёртки:
import { ModalProvider } from "@react-aria/overlays";
function App() {
return (
<ModalProvider>
<MainComponent />
</ModalProvider>
);
}
Все модальные компоненты внутри ModalProvider
автоматически используют созданный контекст для управления фокусом и
aria-атрибутами.
ModalProvider создаёт внутренний React Context, который
можно использовать для доступа к состоянию модальных окон:
isTopModal(ref) – проверяет, является
ли текущее модальное окно верхним в стеке.addModal(ref) и
removeModal(ref) – регистрируют и снимают
модальные окна со стека.Это особенно важно при реализации множественных модальных окон, чтобы события клавиатуры и фокус корректно обрабатывались только для верхнего окна.
Пример проверки верхнего модального окна:
import { useModalProvider } from "@react-aria/overlays";
function MyModal({ ref }) {
let { isTopModal } = useModalProvider();
useEffect(() => {
if (isTopModal(ref)) {
console.log("Это верхнее модальное окно");
}
}, [ref, isTopModal]);
return <div ref={ref}>Контент модального окна</div>;
}
Одной из важнейших задач ModalProvider является
управление фокусом:
aria-hidden и
становятся недоступными для клавиатуры.Используется комбинация useModal и
useOverlay из @react-aria/overlays:
import { useOverlay, usePreventScroll } from "@react-aria/overlays";
function Modal({ isOpen, onClose, children }) {
let ref = useRef();
usePreventScroll();
let { overlayProps } = useOverlay({ isOpen, onClose, isDismissable: true }, ref);
return (
isOpen && (
<div {...overlayProps} ref={ref} role="dialog" aria-modal="true">
{children}
</div>
)
);
}
usePreventScroll автоматически блокирует прокрутку фона
при открытом модальном окне, а useOverlay обеспечивает
обработку клавиши Escape и клика вне окна для закрытия.
Когда в приложении могут быть открыты несколько модальных окон
одновременно, ModalProvider управляет стеком
окон:
Пример реализации стека:
import { ModalProvider } from "@react-aria/overlays";
function App() {
return (
<ModalProvider>
<ModalA />
<ModalB />
</ModalProvider>
);
}
Здесь ModalB будет верхним окном, пока оно открыто, и
только оно сможет обрабатывать события Escape и клики вне
окна.
ModalProvider хорошо комбинируется с другими
контекстами, например FocusScope из
@react-aria/focus:
FocusScope изолирует фокус внутри модального окна.ModalProvider управляет глобальным стеком модальных
окон.Пример использования FocusScope:
import { FocusScope } from "@react-aria/focus";
function ModalContent() {
return (
<FocusScope contain restoreFocus autoFocus>
<button>Закрыть</button>
<input placeholder="Введите текст" />
</FocusScope>
);
}
contain гарантирует, что фокус не выйдет за пределы
модального окна, а restoreFocus вернёт его на элемент
вызова после закрытия.
ModalProviderModalProvider.useOverlay и
FocusScope для управления доступностью.ModalProvider интегрируется с
usePreventScroll, предотвращая прокрутку фонового
контента.Эта комбинация обеспечивает полностью доступные, безопасные и корректно работающие модальные окна в сложных React-приложениях.