Архитектура библиотеки

Radix UI представляет собой коллекцию низкоуровневых, полностью настраиваемых компонентов для React, ориентированных на создание доступных интерфейсов. Основная цель архитектуры библиотеки — предоставить структурные блоки, которые можно комбинировать и расширять без жестких ограничений на визуальный стиль.


Компонентная модель

Radix UI строится вокруг контейнеров и контроллеров состояния, что обеспечивает гибкость и предсказуемость работы компонентов:

  1. Root-компоненты – служат точкой входа для логики конкретного UI-элемента (например, Dialog.Root, Accordion.Root). Они управляют состоянием, событиями и контекстом для вложенных элементов.
  2. Primitive-компоненты – базовые строительные блоки, предоставляющие минимальный HTML и ARIA-атрибуты. Например, Dialog.Overlay или DropdownMenu.Item обеспечивают доступность без визуальных стилей.
  3. Slot-компоненты – специальные элементы для гибкой вставки пользовательского контента, которые сохраняют контекст родительского компонента. Используются для передачи ref и состояния внутрь дочерних элементов.

Ключевой принцип: каждый компонент делится на «логическую» и «визуальную» части, что позволяет подключать стили и анимации независимо от внутренней логики.


Управление состоянием

Radix UI использует контекст React для централизованного управления состоянием компонентов. Основные подходы:

  • Controlled/Uncontrolled — компоненты могут быть как управляемыми извне, так и автономными. Например, Accordion позволяет передавать значение текущего открытого элемента или управлять им через внутреннее состояние.
  • Context Propagation — дочерние элементы получают доступ к состоянию родителя через контекст, что исключает необходимость «прокидывать пропсы через все уровни».
  • Event Handlers — библиотека предоставляет системные события (onOpenChange, onValueChange), чтобы синхронизировать состояние с внешними контроллерами или стором.

Такой подход обеспечивает гибкость интеграции с любыми архитектурами управления состоянием, включая Redux, Zustand или Recoil.


ARIA и доступность

Каждый компонент Radix UI изначально поддерживает ARIA-атрибуты и корректное управление фокусом:

  • Автоматическое управление aria-expanded, aria-hidden, role.
  • Поддержка навигации с клавиатуры (Tab, ArrowKeys, Escape) для интерактивных элементов.
  • Логика фокусировки и возврата фокуса при открытии/закрытии диалогов, меню и тултипов.
  • Поддержка Roving Focus для списков элементов (например, меню или радио-группы).

Таким образом, архитектура библиотеки обеспечивает доступность по умолчанию, что минимизирует ошибки при интеграции.


Анимации и стилизация

Radix UI не навязывает визуальные стили, вместо этого предоставляя хуки и утилиты для анимации:

  • Компоненты поддерживают transition states: open, closed, intermediate, позволяя подключать CSS или анимации через фреймворки вроде Framer Motion.
  • Использование asChild для подмены корневого элемента на любой React-элемент с сохранением всей логики.
  • ClassName и style пропсы позволяют добавлять кастомные стили без изменения внутренней логики.

Это обеспечивает полное разделение логики и внешнего вида, что соответствует принципам атомарного дизайна.


Архитектурные принципы

  1. Composition over Inheritance — компоненты строятся из маленьких, независимых примитивов, а не наследуются от монолитных классов.
  2. State encapsulation — каждый компонент отвечает за собственное состояние, предоставляя hooks и события для внешней синхронизации.
  3. Accessibility-first — доступность встроена в архитектуру, а не добавляется поверх.
  4. Unopinionated styling — компоненты не содержат готовых тем и стилей, что позволяет интегрировать их в любой дизайн-систему.
  5. Atomic design compatibility — каждый компонент можно комбинировать в сложные интерфейсы без потери контроля над поведением.

Взаимодействие компонентов

В Radix UI компоненты взаимодействуют через согласованные контексты и пропсы:

  • Provider компоненты могут объединять состояние нескольких связанных элементов (например, RadioGroup управляет набором Radio).
  • Trigger и Content элементы взаимодействуют через контекст Root-компонента, передавая состояния открытия/закрытия.
  • Portal используется для рендеринга элементов вне DOM-иерархии, сохраняя доступ к контексту и фокусировку.

Такой подход позволяет создавать модульные, легко тестируемые интерфейсы, где каждое действие компонентов предсказуемо и изолировано.


Расширяемость

Архитектура Radix UI изначально рассчитана на расширение:

  • Возможность подключения кастомных хуков к внутреннему состоянию.
  • Поддержка TypeScript с полными типами для всех компонентов.
  • Использование forwardRef и asChild для гибкой интеграции в сложные интерфейсы.
  • Легкость создания новых примитивов на основе существующих компонентов.

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