Styled Components

Библиотека Radix UI предоставляет низкоуровневые, полностью доступные компоненты пользовательского интерфейса. Для их стилизации часто используется подход с Styled Components, который позволяет писать CSS в JavaScript и создавать компоненты с собственным стилем без глобального загрязнения пространства имён.

Основы интеграции

Для начала необходимо подключить styled-components:

import styled from 'styled-components';
import * as Dialog from '@radix-ui/react-dialog';

Radix UI экспортирует компоненты как React-компоненты, что позволяет их напрямую оборачивать в styled() для создания кастомных версий. Например:

const StyledDialog = styled(Dialog.Root)`
  position: relative;
  z-index: 10;
`;

Важно понимать, что некоторые внутренние элементы Radix требуют обертки отдельно, например, Dialog.Overlay и Dialog.Content.

const Overlay = styled(Dialog.Overlay)`
  background: rgba(0, 0, 0, 0.5);
  position: fixed;
  inset: 0;
`;

const Content = styled(Dialog.Content)`
  background: white;
  border-radius: 8px;
  padding: 20px;
  width: 400px;
  max-width: 90%;
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
`;

Передача пропсов и динамическая стилизация

Styled Components позволяют использовать динамические пропсы для изменения стилей в зависимости от состояния компонента:

const Button = styled.button`
  background-color: ${props => (props.primary ? '#4f46e5' : '#e5e7eb')};
  color: ${props => (props.primary ? 'white' : 'black')};
  padding: 10px 20px;
  border-radius: 6px;
  border: none;
  cursor: pointer;

  &:hover {
    background-color: ${props => (props.primary ? '#4338ca' : '#d1d5db')};
  }
`;

Пример использования с Radix:

import * as Toggle from '@radix-ui/react-toggle';

const StyledToggle = styled(Toggle.Root)`
  background-color: ${props => (props.on ? '#4f46e5' : '#f3f4f6')};
  color: ${props => (props.on ? 'white' : 'black')};
  border-radius: 6px;
  padding: 8px 16px;
  cursor: pointer;
`;

Стилизация анимаций и состояний

Radix UI часто использует data-* атрибуты для управления состояниями компонента. Эти атрибуты можно применять в CSS через styled-components:

const StyledAccordionItem = styled.div`
  border-bottom: 1px solid #e5e7eb;

  &[data-state='open'] {
    background-color: #f9fafb;
  }
`;

Пример для анимации открытия/закрытия:

const StyledAccordionContent = styled.div`
  overflow: hidden;
  transition: max-height 0.3s ease;

  &[data-state='open'] {
    max-height: 500px; /* Достаточно для содержимого */
  }

  &[data-state='closed'] {
    max-height: 0;
  }
`;

Комбинация нескольких компонентов

Radix UI позволяет создавать сложные UI, комбинируя несколько компонентов. Styled Components дают возможность создавать связанные стили для вложенных элементов:

const StyledTabsList = styled(Tabs.List)`
  display: flex;
  border-bottom: 2px solid #e5e7eb;
`;

const StyledTabsTrigger = styled(Tabs.Trigger)`
  padding: 10px 20px;
  cursor: pointer;
  border: none;
  background: none;

  &[data-state='active'] {
    border-bottom: 2px solid #4f46e5;
    color: #4f46e5;
  }
`;

Паттерн “as” для переиспользования

Styled Components поддерживает проп as, что позволяет рендерить компонент как другой элемент или Radix-компонент, сохраняя стили:

const BaseButton = styled.button`
  padding: 12px 24px;
  border-radius: 6px;
  background-color: #4f46e5;
  color: white;
`;

<BaseButton as={Dialog.Trigger}>Open Dialog</BaseButton>

Это особенно полезно для Radix-компонентов, где нужно сохранить семантику, но использовать собственные стили.

Практические рекомендации

  • Всегда использовать data-атрибуты для стилизации состояний (data-state, data-disabled), это упрощает поддержку и предотвращает конфликт с внутренними стилями Radix.
  • Оборачивать каждый Radix-компонент, который рендерит DOM-элемент, в отдельный styled-компонент. Не стоит пытаться стилизовать корневой <Dialog.Root> через CSS напрямую.
  • Для сложных анимаций рекомендуется использовать keyframes и styled.keyframes вместе с data-атрибутами состояний.
  • Сохранять отдельные стили для Overlay и Content, чтобы управлять z-index, позиционированием и адаптивностью.

Примеры комбинаций

<StyledDialog>
  <Overlay />
  <Content>
    <h2>Заголовок модального окна</h2>
    <p>Содержимое модального окна с красивой стилизацией.</p>
    <Dialog.Close asChild>
      <Button>Закрыть</Button>
    </Dialog.Close>
  </Content>
</StyledDialog>

Эта структура демонстрирует сочетание Radix UI и Styled Components для создания модальных окон, сохраняя доступность и полный контроль над стилями.


Radix UI в сочетании с Styled Components позволяет строить полностью кастомные интерфейсы, управлять состояниями через data-* атрибуты и динамически изменять стили с минимальной нагрузкой на кодовую базу. Этот подход упрощает масштабирование и поддержку сложных компонентов.