В библиотеке React Aria позиционирование элементов интерфейса относительно триггера (trigger) играет ключевую роль в создании доступных и предсказуемых пользовательских интерфейсов. Под триггером понимается элемент, который инициирует отображение всплывающего компонента, такого как Tooltip, Popover, Menu или Dialog. React Aria предоставляет набор утилит для корректного вычисления позиции и предотвращения конфликтов с границами экрана.
Trigger и overlay
Anchor и placement
top, bottom, left,
right и их вариации (top-start,
bottom-end и т.д.).Edge detection и collision handling Overlay автоматически корректирует своё положение, чтобы не выйти за пределы viewport. React Aria использует collision detection, предотвращая обрезание или скрытие контента.
useOverlayPositionОсновной хук для позиционирования —
useOverlayPosition. Он вычисляет
координаты для overlay и передаёт необходимые свойства в компонент.
Пример базового использования:
import {useOverlayPosition} from '@react-aria/overlays';
import {useRef} from 'react';
function Tooltip({triggerRef, isOpen, children}) {
const overlayRef = useRef(null);
const {overlayProps, placement} = useOverlayPosition({
targetRef: triggerRef,
overlayRef,
placement: 'top',
offset: 8
});
if (!isOpen) return null;
return (
<div {...overlayProps} ref={overlayRef} style={{position: 'absolute'}}>
{children}
</div>
);
}
Ключевые параметры:
targetRef — ссылка на trigger.overlayRef — ссылка на overlay, используется для
расчёта позиции.placement — предпочтительное направление
отображения.offset — расстояние между trigger и overlay.isOpen — определяет, отображается ли overlay.useOverlayPosition возвращает объект с
overlayProps, которые включают стили позиции
(top, left) и атрибуты для управления фокусом
и взаимодействием.
React Aria автоматически отслеживает изменения размеров viewport и
scroll, обновляя позицию overlay. Для этого достаточно использовать ref
overlay и target, передавая их в useOverlayPosition.
Внутренние слушатели resize и scroll вызывают
перерасчёт координат overlay, что предотвращает смещение относительно
trigger.
const {overlayProps} = useOverlayPosition({
targetRef,
overlayRef,
placement: 'bottom',
shouldFlip: true // позволяет менять позицию при недостатке места
});
shouldFlip — если overlay не помещается, позиция
изменяется на противоположную сторону.containerPadding — задаёт отступ от границ контейнера
или окна для предотвращения выхода overlay за границы.Overlay в React Aria не только визуально позиционируется, но и интегрируется с управлением фокусом и клавиатурными событиями. Используются атрибуты:
aria-labelledby и aria-describedby — для
связи overlay с trigger.role — определяет семантику overlay (menu,
dialog, tooltip).При использовании useOverlayTriggerState позиция overlay
автоматически синхронизируется с состоянием открытия и закрытия, что
обеспечивает доступность через клавиатуру и экранные читалки.
useOverlayTriggerStateЧасто useOverlayPosition используют вместе с
useOverlayTriggerState для управления
видимостью overlay:
import {useOverlayTriggerState} from '@react-stately/overlays';
const state = useOverlayTriggerState({isOpen: false});
const {triggerProps, overlayProps} = useOverlay({
isOpen: state.isOpen,
onClose: state.close
});
Это позволяет:
offset: 4–8px и top/bottom
placement.shouldFlip: true и
containerPadding: 12–16px.useOverlayPosition.overlayRef и targetRef,
чтобы React Aria корректно рассчитывал позиции.shouldFlip и containerPadding
для предотвращения обрезания overlay.ResizeObserver или используйте
встроенные механизмы React Aria для пересчёта позиции.useOverlayPosition, а доступность и фокус —
через useOverlayTriggerState и соответствующие
aria-атрибуты.Позиционирование overlay в React Aria строится на трёх столпах:
targetRef.useOverlayPosition, placement,
offset, shouldFlip.useOverlayTriggerState, aria-атрибуты.Правильное сочетание этих инструментов позволяет создавать предсказуемые, доступные и устойчивые к изменению интерфейса overlay в React-приложениях.