useOverlay — это хук из библиотеки React
Aria, предназначенный для управления поведением оверлеев в
пользовательском интерфейсе. Под оверлеем понимается любой элемент,
который появляется поверх основного контента: модальные окна,
всплывающие подсказки, панели и контекстные меню. Хук обеспечивает
управление фокусом, закрытие по клавишам, обработку кликов вне оверлея и
интеграцию с анимациями.
Основная задача useOverlay — упрощение реализации
доступных и предсказуемых оверлеев, соответствующих стандартам
ARIA и UX.
import { useOverlay } from "@react-aria/overlays";
import { useRef } from "react";
function Modal({ isOpen, onClose, children }) {
const ref = useRef();
const { overlayProps } = useOverlay({ isOpen, onClose }, ref);
return isOpen ? (
<div {...overlayProps} ref={ref} className="modal">
{children}
</div>
) : null;
}
В этом примере overlayProps содержит свойства для
правильной работы оверлея с точки зрения доступности: управление
фокусом, обработка клавиши Escape и события клика вне
элемента.
useOverlay принимает два аргумента:
Основные поля объекта options:
isOpen — логическое значение, определяющее открытость
оверлея.onClose — функция, вызываемая при закрытии оверлея
(например, при клике вне или на Escape).isDismissable — если true, оверлей можно
закрыть кликом вне его границ.isKeyboardDismissDisabled — запрещает закрытие оверлея
по клавише Escape.shouldCloseOnBlur — закрытие оверлея при уходе фокуса
за его пределы.isModal — если true, оверлей блокирует
взаимодействие с контентом позади него.const { overlayProps } = useOverlay(
{
isOpen,
onClose: () => setOpen(false),
isDismissable: true,
isModal: true
},
overlayRef
);
Одна из ключевых функций useOverlay — правильная работа
фокуса:
import { FocusScope } from "@react-aria/focus";
<FocusScope contain restoreFocus autoFocus>
<div {...overlayProps} ref={overlayRef}>
<button>Закрыть</button>
</div>
</FocusScope>
FocusScope интегрируется с useOverlay,
создавая полностью управляемый фокус внутри оверлея.
useOverlay поддерживает несколько способов закрытия:
isKeyboardDismissDisabled не установлен.isDismissable
равен true.onClose
извне (например, кнопка внутри оверлея).const { overlayProps } = useOverlay(
{
isOpen,
onClose,
isDismissable: true
},
overlayRef
);
overlayProps добавляет обработчики
onKeyDown и onPointerDownOutside
автоматически.
Оверлеи часто рендерятся в отдельном DOM-контейнере для корректного
наложения на основной контент. useOverlay легко
интегрируется с React Portal:
import { createPortal } from "react-dom";
return isOpen
? createPortal(
<div {...overlayProps} ref={overlayRef} className="overlay">
{children}
</div>,
document.body
)
: null;
Использование портала обеспечивает правильное позиционирование и управление z-index, не нарушая структуры приложения.
Для всплывающих панелей и контекстных меню важно контролировать
позицию оверлея относительно целевого элемента. Для этого
useOverlay часто комбинируют с
useOverlayPosition:
import { useOverlayPosition } from "@react-aria/overlays";
import { useRef } from "react";
const triggerRef = useRef();
const overlayRef = useRef();
const { overlayProps, placement } = useOverlayPosition({
targetRef: triggerRef,
overlayRef,
placement: "bottom left"
});
<div ref={triggerRef}>Кнопка</div>
<div {...overlayProps} ref={overlayRef}>
Меню
</div>
useOverlayPosition возвращает свойства для
позиционирования и автоматически учитывает прокрутку, размеры окна и
возможные коллизии.
Хотя useOverlay не предоставляет анимации «из коробки»,
он совместим с любыми CSS- или JS-анимациями. Благодаря тому, что
оверлей остаётся в DOM до завершения анимации, можно создавать плавное
появление и исчезновение:
<div
{...overlayProps}
ref={overlayRef}
className={`overlay ${isOpen ? "fade-in" : "fade-out"}`}
>
Контент
</div>
CSS:
.fade-in { opacity: 1; transition: opacity 0.3s; }
.fade-out { opacity: 0; transition: opacity 0.3s; }
FocusScope внутри модальных
оверлеев.isDismissable
или isModal в зависимости от UX.onClose централизованно для всех оверлеев
приложения.useOverlayPosition для динамического
позиционирования.Эти практики позволяют создавать доступные, предсказуемые и легко поддерживаемые оверлеи в React-приложениях.