Radix UI предоставляет мощный набор низкоуровневых компонентов для
построения интерфейсов на React с полной кастомизацией и высокой
доступностью. Одним из ключевых аспектов работы с этими компонентами
является управление позиционированием всплывающих
элементов, таких как модальные окна, тултипы, выпадающие меню и
поповеры. Для этого Radix UI использует модуль
@radix-ui/react-popover и внутренние утилиты для корректной
работы с позиционированием через Popper.js-подобную логику.
Все элементы, требующие позиционирования, в Radix UI строятся вокруг двух ключевых компонентов:
Ключевым свойством является side,
определяющее сторону, на которой будет отображаться контент относительно
триггера. Возможные значения:
side: 'top' | 'right' | 'bottom' | 'left'
Пример:
<Popover.Root>
<Popover.Trigger>Открыть</Popover.Trigger>
<Popover.Content side="bottom">
Контент появляется снизу
</Popover.Content>
</Popover.Root>
Для тонкой настройки позиции используется
align и
sideOffset:
align определяет выравнивание по оси, перпендикулярной
side:align: 'start' | 'center' | 'end'
sideOffset задаёт отступ от триггера в пикселях:<Popover.Content side="right" align="start" sideOffset={8}>
Выравнивание по левому краю триггера
</Popover.Content>
Radix UI автоматически обрабатывает случаи, когда контент может выйти
за пределы окна. Для этого используется свойство
collisionPadding, которое задаёт
минимальное расстояние до границ окна:
<Popover.Content collisionPadding={12}>
Контент будет смещён, если достигнет края окна
</Popover.Content>
Также поддерживаются стратегии поведения при переполнении через
avoidCollisions (по умолчанию true).
Позиционируемый элемент можно плавно анимировать с помощью CSS или
через библиотеку Radix Motion, применяя
трансформации к свойствам side и align.
Например, для появления снизу можно задать:
[data-state='open'] {
transform: translateY(0);
opacity: 1;
transition: transform 0.2s ease, opacity 0.2s ease;
}
[data-state='closed'] {
transform: translateY(-10px);
opacity: 0;
}
Radix добавляет атрибут data-state автоматически для
управления анимацией.
Для корректного позиционирования вне родительского контекста
используется Portal:
<Popover.Portal>
<Popover.Content side="top">
Контент рендерится в body
</Popover.Content>
</Popover.Portal>
Это важно для избежания проблем с overflow: hidden или
z-index родителя.
Radix UI позволяет динамически изменять позицию при изменении размеров окна или прокрутке. Для этого используются:
onOpenChange — обработка
открытия/закрытия с возможностью вручную корректировать позицию.align + side комбинации —
создают адаптивное поведение контента.collisionBoundary — возможность задать
кастомные границы, отличные от окна браузера.Пример адаптивного поповера:
<Popover.Content
side="bottom"
align="center"
sideOffset={10}
collisionPadding={8}
avoidCollisions
>
Динамически позиционируемый контент
</Popover.Content>
Portal, чтобы избежать проблем с родительскими
стилями.sideOffset для создания визуального
пространства между триггером и контентом.collisionPadding и
avoidCollisions для корректной работы на малых экранах и
при изменении размеров окна.side и align для достижения
точного позиционирования и согласованного UX.data-state, чтобы
обеспечить синхронизацию с внутренней логикой Radix.Эти принципы позволяют создавать интерфейсы с предсказуемым, гибким и доступным позиционированием, сохраняя полную контроль над внешним видом и поведением компонентов Radix UI.