В библиотеке Radix UI аккордеоны реализуются через
компонент Accordion, который позволяет создавать
интерактивные сворачиваемые панели. Вложенные
аккордеоны расширяют возможности стандартного компонента,
позволяя организовывать многоуровневую структуру контента без потери
управляемости и доступности.
В Radix UI каждый аккордеон состоит из трёх ключевых элементов:
Accordion.Root – контейнер для всей структуры
аккордеона. Может иметь режим single или
multiple.Accordion.Item – отдельный элемент аккордеона, который
содержит заголовок и панель с контентом.Accordion.Trigger и Accordion.Content –
элементы, управляющие открытием и отображением содержимого.Для вложенного аккордеона важно соблюдать правильную
структуру DOM, чтобы каждый уровень имел свой собственный
Accordion.Root. Это предотвращает конфликты состояния между
уровнями.
import * as Accordion from '@radix-ui/react-accordion';
<Accordion.Root type="single" collapsible>
<Accordion.Item value="item-1">
<Accordion.Trigger>Первый уровень</Accordion.Trigger>
<Accordion.Content>
Контент первого уровня
<Accordion.Root type="multiple">
<Accordion.Item value="nested-1">
<Accordion.Trigger>Вложенный уровень 1</Accordion.Trigger>
<Accordion.Content>Контент вложенного уровня 1</Accordion.Content>
</Accordion.Item>
<Accordion.Item value="nested-2">
<Accordion.Trigger>Вложенный уровень 2</Accordion.Trigger>
<Accordion.Content>Контент вложенного уровня 2</Accordion.Content>
</Accordion.Item>
</Accordion.Root>
</Accordion.Content>
</Accordion.Item>
</Accordion.Root>
Каждый Accordion.Root в Radix UI имеет
собственное состояние, которое можно контролировать как
внутренне, так и внешне. Для внешнего управления используется проп
value и событие onValueChange.
const [outerValue, setOuterValue] = React.useState('');
const [innerValue, setInnerValue] = React.useState([]);
<Accordion.Root type="single" value={outerValue} onValueCha nge={setOuterValue}>
<Accordion.Item value="item-1">
<Accordion.Trigger>Первый уровень</Accordion.Trigger>
<Accordion.Content>
<Accordion.Root type="multiple" value={innerValue} onValueCha nge={setInnerValue}>
<Accordion.Item value="nested-1">
<Accordion.Trigger>Вложенный 1</Accordion.Trigger>
<Accordion.Content>Контент 1</Accordion.Content>
</Accordion.Item>
<Accordion.Item value="nested-2">
<Accordion.Trigger>Вложенный 2</Accordion.Trigger>
<Accordion.Content>Контент 2</Accordion.Content>
</Accordion.Item>
</Accordion.Root>
</Accordion.Content>
</Accordion.Item>
</Accordion.Root>
Использование разделения состояний на каждом уровне обеспечивает точный контроль над открытыми панелями и предотвращает случайное закрытие вложенных элементов при манипуляции родительским аккордеоном.
Radix UI автоматически обеспечивает доступность компонентов аккордеона:
aria-controls и id для связи
Trigger и Content.Trigger внутри одного Accordion.Root.При вложенных аккордеонах важно, чтобы каждый уровень имел уникальные идентификаторы, иначе поведение клавиатурного управления может быть нарушено.
<Accordion.Item value="item-1" id="parent-1">
<Accordion.Trigger id="trigger-1" aria-controls="content-1">Первый уровень</Accordion.Trigger>
<Accordion.Content id="content-1">...</Accordion.Content>
</Accordion.Item>
Radix UI не навязывает визуальный стиль, но предоставляет ключевые состояния для стилизации через CSS и сторонние библиотеки:
data-state="open" или data-state="closed"
у Accordion.Item.data-disabled="true" для отключённых элементов.max-height
или библиотек анимаций, например, Framer Motion.[data-state="open"] {
animation: expand 0.3s ease-out forwards;
}
[data-state="closed"] {
animation: collapse 0.3s ease-in forwards;
}
@keyframes expand {
from { max-height: 0; opacity: 0; }
to { max-height: 500px; opacity: 1; }
}
@keyframes collapse {
from { max-height: 500px; opacity: 1; }
to { max-height: 0; opacity: 0; }
}
value и id –
предотвращают конфликты при рендеринге нескольких уровней.type="multiple" для вложенных
элементов – часто позволяет пользователю одновременно открывать
несколько панелей на подуровне.Вложенные аккордеоны Radix UI позволяют создавать сложные интерактивные интерфейсы с полным контролем над состоянием и визуальной презентацией, сохраняя при этом принципы доступности и предсказуемого поведения компонентов.