Gatsby

Для начала работы с 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

Каждый компонент 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 предоставляет только логическую оболочку, стилизация полностью зависит от разработчика. Рекомендуемые подходы:

Использование Tailwind CSS

<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">
  • Применение утилит Tailwind позволяет быстро менять размеры, цвета, позиционирование.
  • Псевдоклассы 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; } }
  • Все компоненты Radix UI автоматически ставят 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 — основной элемент меню, можно использовать кастомные обработчики событий.
  • Поддержка клавиатурной навигации и ARIA-атрибутов по умолчанию.

Tooltip

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 добавляет треугольник у подсказки.
  • Tooltip полностью совместим с SSR и безопасен для Gatsby.

Работа с анимациями и состояниями

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;
}

Такой подход позволяет создавать плавные эффекты без сторонних библиотек.


Интеграция с Gatsby и SEO

  • Server-Side Rendering: Radix UI полностью совместим с SSR, так как компоненты используют обычный React.
  • Аксессибилити: встроенные ARIA-атрибуты (aria-expanded, aria-controls, role) улучшают доступность и SEO.
  • Lazy Loading: компоненты можно загружать динамически через 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>

Продвинутые техники

  • Композиция компонентов: Radix UI позволяет объединять Popover внутри Dialog, создавая сложные интерфейсы.
  • Состояние через controlled props: компоненты можно контролировать через 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>
  • Совместимость с CSS-in-JS: можно использовать styled-components или @emotion/styled для полной кастомизации без потери типов.

Radix UI в сочетании с Gatsby предоставляет мощную платформу для создания высокодоступных, кастомизируемых UI-компонентов. Сочетание headless-архитектуры, семантической разметки, поддержки SSR и простоты интеграции с любыми системами стилей делает библиотеку универсальным инструментом для современного фронтенда.