Библиотека Radix UI построена на концепции примитивов интерфейса. Каждый компонент состоит из нескольких взаимосвязанных частей, которые формируют полноценное поведение интерфейсного элемента. Вместо монолитного компонента разработчику предоставляется набор структурных блоков, объединённых общей логикой состояния и взаимодействия.
Наиболее фундаментальные элементы практически всех компонентов Radix UI:
Эти элементы формируют основу интерактивных интерфейсных паттернов: выпадающих меню, попапов, диалоговых окон, тултипов, аккордеонов, контекстных меню и других сложных UI-структур.
Root представляет корневой контейнер
компонента.
Он выполняет несколько ключевых функций:
Фактически Root — это центральный управляющий
узел, через который проходит вся внутренняя логика
компонента.
Типичная структура компонента Radix UI выглядит следующим образом:
import * as Dialog from "@radix-ui/react-dialog";
<Dialog.Root>
<Dialog.Trigger />
<Dialog.Content />
</Dialog.Root>
Здесь:
Root управляет состояниемTrigger инициирует действиеContent отображает интерфейсRoot может работать в двух режимах:
1. Неконтролируемый режим
Состояние управляется самим компонентом.
<Dialog.Root>
В этом режиме библиотека самостоятельно отслеживает:
2. Контролируемый режим
Состояние управляется извне через React.
const [open, setOpen] = useState(false);
<Dialog.Root open={open} onOpenCha nge={setOpen}>
Основные свойства:
| Свойство | Назначение |
|---|---|
open |
текущее состояние |
defaultOpen |
начальное состояние |
onOpenChange |
обработчик изменения |
Такой подход позволяет интегрировать компонент в сложные состояния приложения.
Root создаёт React Context, который
используется дочерними элементами:
TriggerContentOverlayPortalЧерез этот контекст передаются:
Это позволяет дочерним элементам взаимодействовать без прямой передачи props.
Root также отвечает за контроль фокуса,
включая:
Такая логика необходима для соблюдения стандартов доступности (ARIA).
import * as Popover from "@radix-ui/react-popover";
<Popover.Root>
<Popover.Trigger>Open</Popover.Trigger>
<Popover.Content>
Popover content
</Popover.Content>
</Popover.Root>
Popover.Root управляет:
Trigger — элемент, который инициирует действие
компонента.
Он отвечает за:
В большинстве компонентов Trigger — это кнопка
или интерактивный элемент.
<Popover.Trigger>
Open popover
</Popover.Trigger>
При взаимодействии пользователя происходит изменение состояния
Root.
Trigger автоматически подключён к Root
через контекст.
Поэтому без дополнительного кода реализуются:
Radix UI автоматически реализует стандартные клавиатурные взаимодействия:
| Клавиша | Поведение |
|---|---|
| Enter | активация |
| Space | активация |
| Esc | закрытие |
| Tab | навигация |
Эти механизмы встроены в Trigger.
По умолчанию Trigger рендерит button.
Однако часто требуется использовать кастомный элемент.
Для этого используется asChild.
<Popover.Trigger asChild>
<button className="custom-button">
Open
</button>
</Popover.Trigger>
В этом случае:
Это одна из ключевых архитектурных особенностей Radix UI.
Некоторые компоненты допускают несколько Trigger.
Пример:
<Dialog.Root>
<Dialog.Trigger>Open dialog</Dialog.Trigger>
<Dialog.Trigger>Open again</Dialog.Trigger>
</Dialog.Root>
Все триггеры управляют одним состоянием Root.
Trigger автоматически получает ARIA-атрибуты:
aria-expandedaria-controlsdata-stateПример DOM:
<button aria-expanded="true" data-state="open">
Эти атрибуты используются:
Content представляет основное содержимое
компонента, которое отображается после активации
Trigger.
Примеры:
| Компонент | Content |
|---|---|
| Dialog | окно диалога |
| Popover | всплывающая панель |
| Dropdown Menu | список действий |
| Tooltip | подсказка |
<Dialog.Content>
Dialog content
</Dialog.Content>
Этот элемент содержит всю пользовательскую разметку интерфейса.
Во многих компонентах Content рендерится через
React Portal.
Это позволяет:
z-indexПример:
<Dialog.Portal>
<Dialog.Content>
Dialog content
</Dialog.Content>
</Dialog.Portal>
Когда Content открывается, Radix автоматически:
Это критично для:
Content отслеживает события:
pointerdownfocusoutsideescape keyНапример:
<Popover.Content>
Popover
</Popover.Content>
Клик вне области автоматически закрывает поповер.
Для компонентов вроде Popover и Tooltip используется динамическое позиционирование.
Свойства:
| Свойство | Назначение |
|---|---|
side |
сторона отображения |
align |
выравнивание |
sideOffset |
отступ |
Пример:
<Popover.Content
side="bottom"
align="start"
sideOffset={8}
>
Radix UI предоставляет data-атрибуты для CSS-анимаций.
Пример:
[data-state="open"] {
animation: fadeIn 150ms;
}
[data-state="closed"] {
animation: fadeOut 150ms;
}
Также доступны атрибуты:
| Атрибут | Значение |
|---|---|
data-state |
open / closed |
data-side |
top / bottom / left / right |
Это позволяет легко создавать адаптивные анимации.
Во многих компонентах Content используется вместе с
Overlay.
Пример диалога:
<Dialog.Portal>
<Dialog.Overlay />
<Dialog.Content>
Dialog
</Dialog.Content>
</Dialog.Portal>
Overlay создаёт затемнённый фон, а Content
отображает окно.
Внутри Content часто используются элементы закрытия:
<Dialog.Close>Close</Dialog.Close>
Это позволяет управлять состоянием Root изнутри
компонента.
Поскольку Radix не содержит готовых стилей, внешний вид полностью контролируется разработчиком.
Пример:
.popoverContent {
background: white;
border-radius: 6px;
padding: 20px;
box-shadow: 0 10px 25px rgba(0,0,0,0.2);
}
Использование:
<Popover.Content className="popoverContent">
Взаимодействие элементов можно представить следующим образом:
Root
├── Trigger
└── Content
Процесс работы:
TriggerTrigger вызывает изменение состояния в
RootRoot обновляет контекстContent отображается или скрываетсяUser action
↓
Trigger
↓
Root state change
↓
Content render
Эта архитектура обеспечивает:
import * as Popover from "@radix-ui/react-popover";
function Example() {
return (
<Popover.Root>
<Popover.Trigger>
Open
</Popover.Trigger>
<Popover.Portal>
<Popover.Content side="bottom">
Content
<Popover.Close>
Close
</Popover.Close>
</Popover.Content>
</Popover.Portal>
</Popover.Root>
);
}
1. Композиция
Компоненты собираются из независимых примитивов.
2. Контекстное управление
Root передаёт состояние через React Context.
3. Headless-подход
Radix предоставляет поведение, а не стили.
4. Доступность
ARIA-атрибуты, управление фокусом и клавиатурная навигация реализованы автоматически.
| Элемент | Роль |
|---|---|
| Root | управление состоянием |
| Trigger | инициирование действия |
| Content | отображение интерфейса |
Эти три примитива образуют основной архитектурный паттерн Radix UI, который повторяется практически во всех компонентах библиотеки.