Перейти к основному содержимому

Вкладки

Компонент переключения вкладок с контролируемым / неконтролируемым режимами, карточным / линейным внешним видом, закрытием и добавлением вкладок, а также полной поддержкой клавиатуры.

Базовое использование​

Базовое использование
Тушь растекается, дух живости.
Тонкая кисть видна до мелочей.
import { useState } from 'react'
import { LhTabs, LhTabPane } from '@lh-ui/react'

export default function Demo() {
const [value, setValue] = useState('ink')

return (
<LhTabs value={value} onChange={(name) => setValue(name)}>
<LhTabPane name="ink" label="Тушь">
Размытая тушь, живая и плавная.
</LhTabPane>
<LhTabPane name="danqing" label="Даньцин">
Раскраска даньцин, золотое и изумрудное сияние.
</LhTabPane>
</LhTabs>
)
}

Tabs Props​

СвойствоОписаниеТипВариантыПо умолчанию
valueИмя активной вкладки (контролируемое)string——
defaultValueИмя активной вкладки (по умолчанию, неконтролируемое)string——
typeВнешний вид'line' | 'card'—'line'
closableМожно ли закрывать вкладкиboolean—false
addableПоказывать ли кнопку добавленияboolean—false
tabPositionПоложение вкладок'top' | 'bottom'—'top'
sxСокращённые props макетаSxProps——

TabPane Props​

СвойствоОписаниеТипПо умолчанию
nameУникальный идентификатор вкладки (используется как стабильный ключ; динамически менять не рекомендуется)string—
labelЗаголовок вкладкиReactNode—
disabledОтключитьbooleanfalse
childrenСодержимое вкладкиReactNode—

События Tabs​

СобытиеОписаниеСигнатура коллбэкаАналог в Vue
onChangeСрабатывает при смене активной вкладки(name: string) => void@change
onRemoveСрабатывает при закрытии вкладки (видимость вкладки остаётся на усмотрение бизнес-логики)(name: string) => void@remove
onAddСрабатывает по клику на кнопку добавления() => void@add
Контролируемый / неконтролируемый

Передача value делает компонент контролируемым; передача defaultValue включает внутреннее неконтролируемое состояние. onChange срабатывает в обоих режимах. При удалении активной вкладки неконтролируемый режим автоматически переключается на соседнюю доступную вкладку (поведение getNameAfterRemove из plus); в контролируемом режиме это остаётся за бизнес-логикой в onRemove.

Ограничение на дочерние узлы

children должны быть непосредственно элементами LhTabPane (можно выводить их через .map, допускается плоская обёртка во Fragment, но оборачивать в пользовательский компонент нельзя) — родитель собирает записи вкладок, спускаясь через Children.forEach, и пользовательская обёртка ломает сбор.

Взаимодействие с клавиатурой​

Следует шаблону вкладок из APG (tabs pattern): когда фокус находится на кнопке вкладки, ArrowRight / ArrowLeft (либо ArrowDown / ArrowUp в вертикальном режиме) перемещают между доступными вкладками и активируют их, пропуская отключённые; Home / End перемещают к первой / последней вкладке; Delete / Backspace закрывают текущую вкладку (требуется closable). Только активная вкладка имеет tabindex=0, остальные — -1 (roving tabindex).

Доступность​

Лента вкладок имеет role="tablist", вкладки — role="tab" с aria-selected / aria-controls, а панели — role="tabpanel" с aria-labelledby; id генерируются через useId() и стабильны при SSR. Неактивные панели удаляются из дерева доступности атрибутом hidden.

ref​

forwardRef<HTMLDivElement> — корневой элемент. LhTabPane прокидывает HTMLDivElement.

Стили​

import '@lh-ui/react/theme.css'
import '@lh-ui/react/style/tabs'