Управление раскрытием элементов

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


Компоненты для раскрытия

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

  1. Accordion – последовательность раскрывающихся панелей, где пользователь может открывать и закрывать секции.
  2. DropdownMenu – контекстное меню, раскрывающееся по клику или наведению.
  3. Popover – плавающее окно с произвольным контентом, открывающееся относительно привязанного элемента.
  4. Collapsible – компонент для сворачивания/разворачивания содержимого без влияния на структуру DOM.
  5. Dialog – модальное окно, открывающееся поверх контента страницы.

Все эти компоненты используют контролируемое состояние: состояние открытости (open) можно задавать вручную через пропсы, либо полагаться на внутренний контроль библиотеки.


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

Контролируемый компонент в Radix UI:

import * as Accordion from '@radix-ui/react-accordion';
import { useState } from 'react';

function ControlledAccordion() {
  const [openItems, setOpenItems] = useState([]);

  return (
    <Accordion.Root type="multiple" value={openItems} onValueCha nge={setOpenItems}>
      <Accordion.Item value="item-1">
        <Accordion.Header>
          <Accordion.Trigger>Первая секция</Accordion.Trigger>
        </Accordion.Header>
        <Accordion.Content>Содержимое первой секции</Accordion.Content>
      </Accordion.Item>
      <Accordion.Item value="item-2">
        <Accordion.Header>
          <Accordion.Trigger>Вторая секция</Accordion.Trigger>
        </Accordion.Header>
        <Accordion.Content>Содержимое второй секции</Accordion.Content>
      </Accordion.Item>
    </Accordion.Root>
  );
}

Ключевые моменты:

  • type="multiple" позволяет открывать несколько секций одновременно, type="single" ограничивает открытие одной секции.
  • value и onValueChange делают компонент полностью контролируемым из состояния React.
  • Значения value — это уникальные идентификаторы элементов, используемые для синхронизации состояния.

Автоматическое управление раскрытием

Radix UI поддерживает неконтролируемый режим, где библиотека сама управляет состоянием open. Достаточно не указывать value и onValueChange, тогда Radix будет хранить внутреннее состояние.

<Accordion.Root type="single">
  <Accordion.Item value="item-1">
    <Accordion.Header>
      <Accordion.Trigger>Первая секция</Accordion.Trigger>
    </Accordion.Header>
    <Accordion.Content>Контент первой секции</Accordion.Content>
  </Accordion.Item>
</Accordion.Root>

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


Работа с Popover и Dialog

Для компонентов типа Popover и Dialog важно управление открытием через проп open и события onOpenChange:

import * as Popover from '@radix-ui/react-popover';
import { useState } from 'react';

function ExamplePopover() {
  const [open, setOpen] = useState(false);

  return (
    <Popover.Root open={open} onOpenCha nge={setOpen}>
      <Popover.Trigger>Открыть окно</Popover.Trigger>
      <Popover.Content>
        Содержимое Popover
        <Popover.Close>Закрыть</Popover.Close>
      </Popover.Content>
    </Popover.Root>
  );
}

Особенности управления:

  • Popover.Trigger автоматически связывается с контентом, обеспечивая правильное фокусирование.
  • Popover.Close закрывает окно и возвращает фокус на триггер.
  • onOpenChange позволяет синхронизировать состояние с внешними компонентами или логикой.

Анимация раскрытия

Radix UI не предоставляет встроенные анимации, но оставляет возможность добавления CSS-транзишнов:

.accordion-content {
  overflow: hidden;
  transition: height 0.3s ease;
}

С помощью CSS-переменных и состояния data-state="open" можно плавно раскрывать или сворачивать панели:

[data-state="open"] {
  height: auto;
}
[data-state="closed"] {
  height: 0;
}

Доступность (Accessibility)

Radix UI автоматически обрабатывает ARIA-атрибуты:

  • Accordion: aria-expanded, aria-controls.
  • Popover/Dialog: role="dialog", aria-modal, управление фокусом.
  • DropdownMenu: поддержка клавиатуры (ArrowUp, ArrowDown, Enter, Escape).

Это позволяет строить полностью доступные интерфейсы без ручной настройки ARIA.


Сложные сценарии раскрытия

  1. Вложенные аккордеоны — управление раскрытием нескольких уровней с разными типами (single внутри multiple).
  2. Синхронизация состояния Popover с внешним хранилищем — использование Redux или Context для управления открытием в разных частях приложения.
  3. Динамическая генерация элементов — через массивы данных можно создавать любые интерактивные панели с уникальными идентификаторами.

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

  • Всегда использовать уникальные идентификаторы для value, особенно в списках динамически создаваемых элементов.
  • Для модальных и всплывающих окон использовать контролируемый режим для точного управления фокусом.
  • Добавлять плавные CSS-анимации через data-state для улучшения UX.
  • Использовать встроенные ARIA-атрибуты и управление клавиатурой, чтобы обеспечить доступность интерфейса.

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