Для начала работы с Radix UI в проекте на Gatsby требуется установка пакетов библиотеки через npm или yarn. Основные пакеты:
npm install @radix-ui/react-dropdown-menu @radix-ui/react-dialog @radix-ui/react-tooltip
или
yarn add @radix-ui/react-dropdown-menu @radix-ui/react-dialog @radix-ui/react-tooltip
Radix UI предоставляет headless-компоненты, что означает отсутствие встроенных стилей и полную свободу кастомизации. В проектах на Gatsby это особенно удобно, так как можно интегрировать любую CSS-систему (Tailwind, Styled Components, Emotion).
Для корректной работы компонентов важно убедиться, что SSR
(Server-Side Rendering) не вызывает ошибок. Radix UI использует
стандартный React, поэтому проблем с SSR обычно не возникает, но при
работе с portal-элементами иногда требуется проверка
typeof window !== 'undefined' для условного рендера.
Каждый компонент Radix UI имеет контейнерный
компонент и ряд вспомогательных подкомпонентов. Например, для
Dialog:
import * as Dialog from '@radix-ui/react-dialog';
<Dialog.Root>
<Dialog.Trigger>Открыть диалог</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Overlay className="overlay" />
<Dialog.Content className="content">
<Dialog.Title>Заголовок</Dialog.Title>
<Dialog.Description>Описание диалога</Dialog.Description>
<Dialog.Close>Закрыть</Dialog.Close>
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
Ключевые моменты структуры:
Root — корневой компонент, который управляет состоянием
открыто/закрыто.Trigger — элемент, который инициирует открытие
компонента.Portal — переносит контент в отдельное место DOM, что
помогает избегать конфликтов z-index и упрощает позиционирование.Overlay — затемнённая область за модальным окном.Content — контейнер с основным содержимым.Title и Description — семантические
элементы, полезные для доступности.Close — кнопка для закрытия компонента.Такая структура повторяется у большинства компонентов Radix UI:
DropdownMenu, Tooltip, Popover,
что обеспечивает единообразие API.
Radix UI предоставляет только логическую оболочку, стилизация полностью зависит от разработчика. Рекомендуемые подходы:
<Dialog.Overlay className="fixed inset-0 bg-black/50" />
<Dialog.Content className="fixed top-1/2 left-1/2 w-[90%] max-w-md -translate-x-1/2 -translate-y-1/2 bg-white p-6 rounded-lg shadow-lg">
data-state="open" и
data-state="closed" дают возможность анимировать открытие и
закрытие через CSS.data-state[data-state='open'] {
animation: fadeIn 0.2s ease-out forwards;
}
[data-state='closed'] {
animation: fadeOut 0.2s ease-in forwards;
}
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes fadeOut { from { opacity: 1; } to { opacity: 0; } }
data-state, что делает анимации чистыми и
декларативными.import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
<DropdownMenu.Root>
<DropdownMenu.Trigger>Меню</DropdownMenu.Trigger>
<DropdownMenu.Content className="bg-white shadow rounded p-2">
<DropdownMenu.Item className="px-4 py-2 hover:bg-gray-100">Пункт 1</DropdownMenu.Item>
<DropdownMenu.Item className="px-4 py-2 hover:bg-gray-100">Пункт 2</DropdownMenu.Item>
<DropdownMenu.Separator className="my-1 border-t" />
<DropdownMenu.Item className="px-4 py-2 hover:bg-gray-100">Пункт 3</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu.Root>
Особенности:
Separator — визуальный разделитель между пунктами.Item — основной элемент меню, можно использовать
кастомные обработчики событий.import * as Tooltip from '@radix-ui/react-tooltip';
<Tooltip.Provider>
<Tooltip.Root>
<Tooltip.Trigger className="inline-block">Наведи на меня</Tooltip.Trigger>
<Tooltip.Portal>
<Tooltip.Content className="bg-gray-800 text-white rounded px-2 py-1 text-sm">
Подсказка
<Tooltip.Arrow className="fill-gray-800" />
</Tooltip.Content>
</Tooltip.Portal>
</Tooltip.Root>
</Tooltip.Provider>
Provider позволяет управлять глобальными настройками,
такими как задержка показа подсказки (delayDuration).Arrow добавляет треугольник у подсказки.Radix UI не навязывает библиотеку анимаций, но предоставляет data-атрибуты состояния:
data-state="open" /
data-state="closed"data-disabled для блокировки элементовdata-highlighted для подсветки активных элементовПример для анимации DropdownMenu с Tailwind:
[data-state='open'] {
transform: scale(1);
opacity: 1;
transition: all 0.2s ease-out;
}
[data-state='closed'] {
transform: scale(0.95);
opacity: 0;
transition: all 0.15s ease-in;
}
Такой подход позволяет создавать плавные эффекты без сторонних библиотек.
aria-expanded, aria-controls,
role) улучшают доступность и SEO.React.lazy для оптимизации
производительности.Пример динамического импорта:
import React, { Suspense } from 'react';
const Dialog = React.lazy(() => import('@radix-ui/react-dialog'));
<Suspense fallback={null}>
<Dialog.Root>
<Dialog.Trigger>Открыть</Dialog.Trigger>
</Dialog.Root>
</Suspense>
Popover внутри Dialog, создавая
сложные интерфейсы.open и onOpenChange, что
облегчает интеграцию с глобальными менеджерами состояния (Redux,
Zustand).Пример контролируемого Dialog:
const [open, setOpen] = React.useState(false);
<Dialog.Root open={open} onOpenCha nge={setOpen}>
<Dialog.Trigger>Открыть</Dialog.Trigger>
<Dialog.Content>Контент диалога</Dialog.Content>
</Dialog.Root>
styled-components или @emotion/styled для
полной кастомизации без потери типов.Radix UI в сочетании с Gatsby предоставляет мощную платформу для создания высокодоступных, кастомизируемых UI-компонентов. Сочетание headless-архитектуры, семантической разметки, поддержки SSR и простоты интеграции с любыми системами стилей делает библиотеку универсальным инструментом для современного фронтенда.