В библиотеке React Aria элемент
Arrow используется для создания визуальной стрелки,
которая обычно сопровождает компоненты всплывающих элементов:
Tooltip, Popover, Menu и др. Он
обеспечивает корректное позиционирование стрелки относительно целевого
элемента, учитывая направление и смещения, которые задаются системой
позиционирования из React Stately и React
Aria.
Элемент Arrow не является самостоятельным компонентом UI. Он всегда зависит от контекста overlay — элемента, который появляется над основным контентом. Его задача — визуально связывать overlay с элементом-триггером.
import { useOverlayPosition, useOverlayTriggerState } from '@react-stately/overlays';
import { Overlay, OverlayArrow } from '@react-aria/overlays';
Использование стрелки строится вокруг хука
useOverlayPosition, который возвращает координаты для
позиционирования overlay и стрелки.
const state = useOverlayTriggerState({});
const ref = useRef(null);
const overlayRef = useRef(null);
const { overlayProps, arrowProps } = useOverlayPosition({
targetRef: ref,
overlayRef: overlayRef,
placement: 'bottom',
offset: 10,
isOpen: state.isOpen
});
return (
<>
<button ref={ref} onCl ick={state.toggle}>Открыть подсказку</button>
{state.isOpen && (
<Overlay {...overlayProps} ref={overlayRef}>
<div>Содержимое подсказки</div>
<OverlayArrow {...arrowProps} />
</Overlay>
)}
</>
);
В этом примере:
targetRef — ссылка на элемент, относительно которого
будет позиционироваться overlay.overlayRef — ссылка на сам overlay.placement — направление, в котором overlay появляется
относительно target (top, bottom,
left, right, с вариантами -start
и -end).offset — смещение overlay от target.arrowProps — объект с координатами и стилями для
корректного отображения стрелки.OverlayArrow принимает следующие ключевые параметры
через arrowProps:
style — объект с inline-стилями для позиционирования
стрелки (top, left,
transform).ref — ссылка на DOM-элемент стрелки.placement — направление, в котором стрелка «смотрит» на
target.size — размер стрелки (обычно в пикселях, задается
через CSS переменные или классы).Пример кастомизации стрелки:
<OverlayArrow
{...arrowProps}
style={{
...arrowProps.style,
width: '12px',
height: '12px',
backgroundColor: 'black',
clipPath: 'polygon(50% 0%, 0% 100%, 100% 100%)'
}}
/>
clipPath позволяет создать треугольную форму для
стрелки.top, left,
transform) передаются из arrowProps, чтобы
гарантировать правильное положение относительно overlay и target.Стрелка не имеет смысла без overlay, поэтому важно синхронизировать Arrow с состоянием overlay. Обычно это делается через React Stately:
const state = useOverlayTriggerState({ defaultOpen: false });
const triggerRef = useRef(null);
const overlayRef = useRef(null);
const { overlayProps, arrowProps } = useOverlayPosition({
targetRef: triggerRef,
overlayRef: overlayRef,
placement: 'top-start',
isOpen: state.isOpen
});
return (
<>
<button ref={triggerRef} onCl ick={state.toggle}>Кнопка</button>
{state.isOpen && (
<Overlay ref={overlayRef} {...overlayProps}>
<div>Содержимое overlay</div>
<OverlayArrow {...arrowProps} />
</Overlay>
)}
</>
);
placement: 'top-start' указывает, что overlay появится
над кнопкой с выравниванием по левому краю.React Aria учитывает размеры overlay и target, чтобы стрелка не
выходила за границы. Хук useOverlayPosition возвращает
координаты arrowProps.left и arrowProps.top,
которые динамически меняются при изменении размеров окна или
overlay:
window.addEventListener('resize', () => {
// React Aria автоматически пересчитывает позиции
});
Это избавляет от необходимости вручную отслеживать положение стрелки при изменении размеров экрана или элемента.
Для сложных дизайнов удобно использовать CSS-классы:
.arrow {
width: 16px;
height: 16px;
background-color: #333;
clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
}
И применить класс к компоненту:
<OverlayArrow {...arrowProps} className="arrow" />
Стили могут меняться в зависимости от направления стрелки, используя
модификаторы для placement (arrow-top,
arrow-bottom и т.д.).
Стрелка легко интегрируется с анимациями overlay, например, плавное появление при открытии:
<OverlayArrow
{...arrowProps}
style={{
...arrowProps.style,
transition: 'transform 0.2s ease, opacity 0.2s ease',
opacity: state.isOpen ? 1 : 0
}}
/>
transition позволяет анимировать перемещение и
появление стрелки.opacity обеспечивает плавное исчезновение
при закрытии overlay.arrowProps в компонент.
Любые ручные изменения координат могут нарушить синхронизацию.clip-path или SVG для кастомной
формы. Стандартная стрелка — треугольник, но дизайн может
требовать другие формы.placement.Элемент Arrow в React Aria обеспечивает гибкое, корректное и адаптивное позиционирование визуальной связи между overlay и trigger. Он полностью интегрирован с системой overlay и React Stately, что позволяет создавать сложные интерфейсы с подсказками, меню и popover без ручного расчета координат.