useTabs для вкладок

useTabs — это хук, предоставляемый библиотекой React Aria, предназначенный для управления компонентами вкладок с полной поддержкой доступности (accessibility). Он инкапсулирует логику навигации, фокусировки и управления состоянием активной вкладки, позволяя разработчику сосредоточиться на визуальном отображении интерфейса.

Хук автоматически обрабатывает:

  • Выбор активной вкладки через клик или клавиатуру.
  • Фокусировку вкладок с помощью стрелок (влево/вправо или вверх/вниз в вертикальном режиме).
  • ARIA-атрибуты (aria-selected, aria-controls, role="tablist", role="tab", role="tabpanel") для корректного взаимодействия с экранными читалками.

Использование useTabs на практике

Для базового применения useTabs требуется два основных компонента:

  1. Контейнер для вкладок (TabList)
  2. Панель содержимого (TabPanel) для каждой вкладки

Пример структуры:

import { useTabs, useTab, useTabPanel } from '@react-aria/tabs';
import { useTabListState } from '@react-stately/tabs';

function TabsExample() {
  const state = useTabListState({
    selectedKey: 'tab1',
    onSelectionChange: key => console.log(key),
    items: [
      { key: 'tab1', name: 'Вкладка 1' },
      { key: 'tab2', name: 'Вкладка 2' },
      { key: 'tab3', name: 'Вкладка 3' },
    ]
  });

  const { tabListProps } = useTabs({ orientation: 'horizontal' }, state);

  return (
    <div>
      <div {...tabListProps}>
        {state.collection.map(item => (
          <Tab key={item.key} item={item} state={state} />
        ))}
      </div>
      {state.collection.map(item => (
        <TabPanel key={item.key} item={item} state={state} />
      ))}
    </div>
  );
}

function Tab({ item, state }) {
  const ref = React.useRef();
  const { tabProps } = useTab({ key: item.key }, state, ref);

  return (
    <button {...tabProps} ref={ref}>
      {item.name}
    </button>
  );
}

function TabPanel({ item, state }) {
  const ref = React.useRef();
  const { tabPanelProps } = useTabPanel({ key: item.key }, state, ref);

  return state.selectedKey === item.key ? (
    <div {...tabPanelProps} ref={ref}>
      Контент {item.name}
    </div>
  ) : null;
}

Основные параметры и возможности

Параметры useTabs

  • orientation'horizontal' или 'vertical'. Определяет направление вкладок и клавиши навигации.

  • keyboardActivation'automatic' или 'manual'.

    • automatic – переключение вкладки при перемещении фокуса стрелками.
    • manual – вкладка меняется только при нажатии Enter или Space.
  • onSelectionChange – функция, вызываемая при изменении выбранной вкладки.

Параметры useTab

  • key – уникальный идентификатор вкладки.
  • disabled – флаг, запрещающий выбор вкладки.
  • Возвращает tabProps, которые включают все необходимые ARIA-атрибуты и обработчики событий.

Параметры useTabPanel

  • key – идентификатор панели, соответствующий вкладке.
  • Возвращает tabPanelProps, включая role="tabpanel" и aria-labelledby.

Поддержка клавиатуры и фокуса

useTabs автоматически обеспечивает навигацию через:

  • Горизонтальные вкладки: стрелки влево/вправо для перехода между вкладками.
  • Вертикальные вкладки: стрелки вверх/вниз.
  • Home/End – перемещение к первой и последней вкладке.
  • Enter/Space – активация вкладки (если keyboardActivation равен 'manual').

Фокус перемещается на следующую активную вкладку, а ARIA-атрибуты обновляются автоматически, обеспечивая совместимость с экранными читалками.


Состояние вкладок с useTabListState

Хук useTabListState из React Stately хранит и управляет состоянием:

  • selectedKey – текущая активная вкладка.
  • collection – массив вкладок.
  • disabledKeys – список недоступных вкладок.
  • onSelectionChange – колбэк при смене активной вкладки.

Пример динамического обновления:

state.selectedKey = 'tab2'; // программная смена вкладки

Поддержка доступности (ARIA)

React Aria делает вкладки полностью доступными:

  • role=“tablist” – контейнер для вкладок.
  • role=“tab” – каждая вкладка.
  • aria-selected=“true/false” – текущая активная вкладка.
  • aria-controls – связывает вкладку с соответствующей панелью.
  • role=“tabpanel” – область содержимого.
  • aria-labelledby – связывает панель с заголовком вкладки.

Эта структура гарантирует корректное взаимодействие с экранными читалками и клавиатурой.


Вертикальные и горизонтальные вкладки

useTabs позволяет легко менять ориентацию:

const { tabListProps } = useTabs({ orientation: 'vertical' }, state);
  • Горизонтальные вкладки чаще используются для главных меню.
  • Вертикальные — для боковых панелей или списков настроек.

Клавиши навигации автоматически адаптируются под ориентацию.


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

  • Automatic: навигация стрелками меняет активную вкладку сразу.
  • Manual: стрелки только перемещают фокус, выбор происходит Enter/Space.

Пример:

const { tabListProps } = useTabs(
  { orientation: 'horizontal', keyboardActivation: 'manual' },
  state
);

Это полезно, если содержимое вкладки тяжелое для рендеринга или требует подтверждения.


Итоговые рекомендации по применению

  • Использовать useTabs вместе с useTabListState для управления состоянием.
  • Для каждой вкладки использовать useTab с уникальным key.
  • Панели содержимого связывать с вкладками через useTabPanel.
  • Обязательно передавать orientation для корректной навигации.
  • Настраивать keyboardActivation в зависимости от UX и производительности рендеринга.

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