Управление активной вкладкой

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

  • Контролируемый режим позволяет полностью управлять активной вкладкой через проп value.
  • Неконтролируемый режим использует defaultValue для первоначального выбора вкладки, после чего состояние управляется внутренне библиотекой.

Пример базового использования в контролируемом режиме:

import * as Tabs from '@radix-ui/react-tabs';
import { useState } from 'react';

function Example() {
  const [activeTab, setActiveTab] = useState('tab1');

  return (
    <Tabs.Root value={activeTab} onValueCha nge={setActiveTab}>
      <Tabs.List>
        <Tabs.Trigger value="tab1">Вкладка 1</Tabs.Trigger>
        <Tabs.Trigger value="tab2">Вкладка 2</Tabs.Trigger>
      </Tabs.List>
      <Tabs.Content value="tab1">Контент первой вкладки</Tabs.Content>
      <Tabs.Content value="tab2">Контент второй вкладки</Tabs.Content>
    </Tabs.Root>
  );
}

Свойства и события компонента Tabs.Root

  • value — текущая активная вкладка (только в контролируемом режиме).
  • defaultValue — вкладка, выбранная по умолчанию (неконтролируемый режим).
  • onValueChange — коллбек, вызываемый при изменении активной вкладки, принимает новое значение.
  • orientation — ориентация вкладок: horizontal или vertical.
  • activationMode — режим активации: automatic (при наведении) или manual (только по клику).

Пример вертикальных вкладок с ручной активацией:

<Tabs.Root orientation="vertical" activationMode="manual">
  <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>

Динамическое управление вкладками

Radix UI позволяет динамически изменять активную вкладку программно. Это достигается изменением состояния, связанного с value. Можно реализовать автоматический переход на вкладку по событию, например, после успешного API-запроса:

function DynamicTabs({ apiResult }) {
  const [activeTab, setActiveTab] = useState('tab1');

  useEffect(() => {
    if (apiResult.success) {
      setActiveTab('tab2');
    }
  }, [apiResult]);

  return (
    <Tabs.Root value={activeTab} onValueCha nge={setActiveTab}>
      <Tabs.List>
        <Tabs.Trigger value="tab1">Старт</Tabs.Trigger>
        <Tabs.Trigger value="tab2">Результаты</Tabs.Trigger>
      </Tabs.List>
      <Tabs.Content value="tab1">Начальная вкладка</Tabs.Content>
      <Tabs.Content value="tab2">Вкладка с результатами</Tabs.Content>
    </Tabs.Root>
  );
}

Управление фокусом и доступностью

Radix UI автоматически обрабатывает фокус и клавиатурную навигацию между вкладками:

  • ArrowRight / ArrowDown — переход к следующей вкладке.
  • ArrowLeft / ArrowUp — переход к предыдущей вкладке.
  • Home — переход к первой вкладке.
  • End — переход к последней вкладке.

При ручном управлении состоянием важно синхронизировать value с фокусом, чтобы обеспечить корректную навигацию с клавиатуры.

Ленивая загрузка содержимого вкладок

Для оптимизации производительности используется проп forceMount в Tabs.Content.

  • forceMount={true} — контент вкладки всегда монтируется, даже если она неактивна.
  • По умолчанию контент монтируется только при активации вкладки, что позволяет экономить ресурсы.
<Tabs.Content value="tab1" forceMount>
  Контент первой вкладки всегда монтируется
</Tabs.Content>

Интеграция с библиотеками состояния

Контролируемые вкладки легко интегрируются с React Router или состоянием глобального менеджера, например, Redux или Zustand:

import { useStore } from './store';

function RouterTabs() {
  const { currentTab, setCurrentTab } = useStore();

  return (
    <Tabs.Root value={currentTab} onValueCha nge={setCurrentTab}>
      <Tabs.List>
        <Tabs.Trigger value="home">Главная</Tabs.Trigger>
        <Tabs.Trigger value="profile">Профиль</Tabs.Trigger>
      </Tabs.List>
      <Tabs.Content value="home">Контент главной</Tabs.Content>
      <Tabs.Content value="profile">Контент профиля</Tabs.Content>
    </Tabs.Root>
  );
}

Рекомендации по архитектуре

  • Использовать контролируемый режим, если активная вкладка должна зависеть от состояния приложения.
  • Использовать неконтролируемый режим для простых интерфейсов, где нет необходимости синхронизировать состояние с внешним кодом.
  • Применять forceMount только для вкладок с дорогостоящей логикой монтирования, иначе оставлять ленивую загрузку.
  • Поддерживать orientation и activationMode для улучшения UX и доступности.

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