Radix UI представляет собой набор низкоуровневых, доступных и настраиваемых компонентов для React-приложений. Главная идея библиотеки — предоставить разработчику полный контроль над стилями и поведением компонентов, оставляя при этом гарантию доступности и корректного взаимодействия с пользователем.
Для начала работы с Radix UI требуется установка пакета через npm или yarn:
npm install @radix-ui/react-primitive @radix-ui/react-dialog @radix-ui/react-dropdown-menu
Каждый компонент поставляется отдельным модулем, что позволяет
подключать только необходимый функционал. Например,
@radix-ui/react-dialog используется для создания модальных
окон, а @radix-ui/react-dropdown-menu — для выпадающих
меню.
Импорт компонентов в проект осуществляется следующим образом:
import * as Dialog from '@radix-ui/react-dialog';
import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
Использование namespace (* as) позволяет группировать
все элементы компонента под одной переменной, что облегчает читаемость и
поддержку кода.
В контексте Radix UI инвертирование часто применяется при работе с
контролируемыми и неконтролируемыми состояниями компонентов. Например,
диалоговое окно (Dialog) может управляться как внешне
(через проп open), так и внутренне (через локальное
состояние).
Пример внешнего управления состоянием:
const [isOpen, setIsOpen] = React.useState(false);
<Dialog.Root open={isOpen} onOpenCha nge={setIsOpen}>
<Dialog.Trigger>Открыть окно</Dialog.Trigger>
<Dialog.Content>
<Dialog.Title>Заголовок окна</Dialog.Title>
<Dialog.Description>Описание содержания окна</Dialog.Description>
</Dialog.Content>
</Dialog.Root>
Инвертирование состояния здесь заключается в том,
что нажатие кнопки Trigger меняет состояние с
false на true и обратно, обеспечивая
синхронизацию интерфейса с логикой приложения.
DropdownMenuВыпадающее меню требует контроля видимости элементов. Radix UI
предоставляет open и onOpenChange, позволяя
инвертировать текущее состояние при определённых действиях:
const [menuOpen, setMenuOpen] = React.useState(false);
<DropdownMenu.Root open={menuOpen} onOpenCha nge={setMenuOpen}>
<DropdownMenu.Trigger>Меню</DropdownMenu.Trigger>
<DropdownMenu.Content>
<DropdownMenu.Item>Пункт 1</DropdownMenu.Item>
<DropdownMenu.Item>Пункт 2</DropdownMenu.Item>
</DropdownMenu.Content>
</DropdownMenu.Root>
Если требуется создать функционал «закрыть при повторном клике», используется инвертирование состояния:
const toggleMenu = () => setMenuOpen(prev => !prev);
Такой подход позволяет синхронизировать внешний UI и внутреннее состояние компонента без необходимости вручную проверять текущее состояние меню.
Radix UI предоставляет только логику и accessibility, поэтому визуальная часть оформляется через сторонние библиотеки. Инвертирование состояния тесно связано с динамическими классами:
<Dialog.Content
className={`bg-white p-6 rounded shadow-lg transition-transform ${
isOpen ? 'scale-100 opacity-100' : 'scale-95 opacity-0'
}`}
>
Содержимое окна
</Dialog.Content>
Изменение классов при инверсии состояния позволяет создавать анимации открытия и закрытия компонентов без потери доступности.
Radix UI автоматически управляет фокусом, что особенно важно при
инверсном управлении состояниями. При открытии Dialog фокус
переводится на первый интерактивный элемент, а при закрытии возвращается
к Trigger.
Для кастомного управления можно использовать
onOpenChange, чтобы выполнять дополнительные действия:
<Dialog.Root
open={isOpen}
onOpenCha nge={(state) => {
setIsOpen(state);
if (state) console.log('Диалог открыт');
else console.log('Диалог закрыт');
}}
>
Инвертирование состояния позволяет объединять логику отображения с другими событиями интерфейса, например, закрытием всех меню при открытии модального окна.
Radix UI поддерживает вложенные компоненты, что делает инвертирование
состояния особенно полезным. Например, вложенные
DropdownMenu элементы могут иметь собственные
open состояния, синхронизированные с родительским меню:
<DropdownMenu.Sub>
<DropdownMenu.SubTrigger>Подменю</DropdownMenu.SubTrigger>
<DropdownMenu.SubContent>
<DropdownMenu.Item>Подпункт 1</DropdownMenu.Item>
</DropdownMenu.SubContent>
</DropdownMenu.Sub>
Использование инверсного подхода в этих случаях помогает поддерживать открытость только одного подменю за раз.
React.useState для инвертирования
boolean-состояний компонентов.open и
onOpenChange, чтобы избежать рассинхронизации UI и
логики.Интеграция Radix UI с инверсным управлением состояний обеспечивает высокий контроль над UI, гибкость кастомизации и сохранение доступности, что делает библиотеку мощным инструментом для создания интерактивных и отзывчивых интерфейсов.