Библиотека Radix UI предоставляет мощный набор компонентов для создания интерактивных пользовательских интерфейсов. Один из ключевых компонентов — это Tabs, который позволяет организовать различные секции интерфейса в виде вкладок с соответствующим контентом. Управление контентом вкладок осуществляется с помощью компонента Tabs.Content.
Компонент Tabs состоит из трёх базовых элементов:
Пример базовой структуры:
import * as Tabs from '@radix-ui/react-tabs';
<Tabs.Root defaultValue="tab1">
<Tabs.List>
<Tabs.Trigger value="tab1">Вкладка 1</Tabs.Trigger>
<Tabs.Trigger value="tab2">Вкладка 2</Tabs.Trigger>
<Tabs.Trigger value="tab3">Вкладка 3</Tabs.Trigger>
</Tabs.List>
<Tabs.Content value="tab1">
Контент первой вкладки
</Tabs.Content>
<Tabs.Content value="tab2">
Контент второй вкладки
</Tabs.Content>
<Tabs.Content value="tab3">
Контент третьей вкладки
</Tabs.Content>
</Tabs.Root>
Ключевой момент: value в
Tabs.Content должно совпадать с value
соответствующего Tabs.Trigger. Только тогда содержимое
будет правильно отображаться при переключении вкладок.
Компонент Tabs.Content по умолчанию скрывает контент
неактивных вкладок, используя CSS-свойство display: none.
Это позволяет экономить ресурсы браузера и предотвращает лишний
рендеринг.
Можно управлять анимацией появления и скрытия с помощью CSS или библиотек типа Framer Motion. Пример с плавным появлением:
.tabsContent {
opacity: 0;
transition: opacity 0.3s ease-in-out;
}
.tabsContent[data-state='active'] {
opacity: 1;
}
<Tabs.Content value="tab1" className="tabsContent">
Плавно отображаемый контент
</Tabs.Content>
Совет: использование атрибута
data-state позволяет создавать кастомные стили для
активного и неактивного контента.
Radix UI позволяет создавать вкладки и контент динамически из массива данных. Это особенно полезно для интерфейсов с большим количеством вкладок, где жестко прописывать каждую вкладку неудобно.
Пример динамического создания:
const tabsData = [
{ id: 'tab1', title: 'Вкладка 1', content: 'Контент первой вкладки' },
{ id: 'tab2', title: 'Вкладка 2', content: 'Контент второй вкладки' },
{ id: 'tab3', title: 'Вкладка 3', content: 'Контент третьей вкладки' },
];
<Tabs.Root defaultValue={tabsData[0].id}>
<Tabs.List>
{tabsData.map(tab => (
<Tabs.Trigger key={tab.id} value={tab.id}>
{tab.title}
</Tabs.Trigger>
))}
</Tabs.List>
{tabsData.map(tab => (
<Tabs.Content key={tab.id} value={tab.id}>
{tab.content}
</Tabs.Content>
))}
</Tabs.Root>
Преимущество: такой подход упрощает поддержку кода и позволяет легко добавлять или удалять вкладки без изменений логики отображения контента.
Внутри Tabs.Content можно размещать любые React-компоненты: формы, таблицы, графики, списки и другие UI-элементы. Radix UI корректно управляет их монтированием и размонтированием при переключении вкладок.
Пример с формой внутри вкладки:
<Tabs.Content value="tab1">
<form>
<label>
Имя:
<input type="text" name="name" />
</label>
<button type="submit">Отправить</button>
</form>
</Tabs.Content>
Особенность: состояние компонентов внутри
Tabs.Content сохраняется, если не удалять компонент
полностью из DOM. Для полной очистки состояния при переключении можно
использовать условный рендеринг
({activeTab === 'tab1' && <Form />}).
Radix UI предоставляет низкоуровневые стили, оставляя разработчику свободу для кастомизации. Для Tabs.Content доступны следующие точки кастомизации:
className – для применения CSS-классов.data-state – активен или неактивен (active
/ inactive).data-orientation – горизонтальная или вертикальная
ориентация вкладок (horizontal /
vertical).Пример стилизации для вертикальных вкладок:
.tabsContent[data-orientation='vertical'] {
padding: 16px;
border-left: 2px solid #333;
}
<Tabs.Root orientation="vertical" defaultValue="tab1">
...
<Tabs.Content value="tab1">Контент вертикальной вкладки</Tabs.Content>
</Tabs.Root>
Radix UI автоматически добавляет правильные ARIA-атрибуты для вкладок и контента, что обеспечивает:
Для Tabs.Content используются атрибуты:
role="tabpanel" – идентифицирует панель как контент
вкладки.aria-labelledby – связывает контент с заголовком
вкладки.Это позволяет создавать полностью доступные интерфейсы без дополнительной ручной работы.
value, соответствующий
Tabs.Trigger.data-state для кастомных анимаций и
стилей.className и атрибуты
ориентации.