Skip to content
API 风格:

Вкладки ​

Переключение содержимого одного уровня. Строго следует шаблону вкладок WAI-ARIA APG: три связанные роли tablist/tab/tabpanel + roving tabindex + навигация стрелками.

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

Базовое использование
Содержимое прозы в стиле туши.
vue
<script setup lang="ts">
</script>

<template>
  <LhTabs>
    <LhTabPane name="prose" label="Проза">Содержимое прозы в стиле туши.</LhTabPane>
    <LhTabPane name="poem" label="Поэзия">Содержимое о стихотворных формах.</LhTabPane>
    <LhTabPane name="calligraphy" label="Каллиграфия">Содержимое о каллиграфических эталонах.</LhTabPane>
  </LhTabs>
</template>
vue
<script>
export default {}
</script>

<template>
  <LhTabs>
    <LhTabPane name="prose" label="Проза">Содержимое прозы в стиле туши.</LhTabPane>
    <LhTabPane name="poem" label="Поэзия">Содержимое о стихотворных формах.</LhTabPane>
    <LhTabPane name="calligraphy" label="Каллиграфия">Содержимое о каллиграфических эталонах.</LhTabPane>
  </LhTabs>
</template>

Карточный внешний вид и отключение ​

Карточный внешний вид и отключение
Тушь бывает пяти оттенков.
vue
<script setup lang="ts">
</script>

<template>
  <LhTabs type="card">
    <LhTabPane name="ink" label="Тушь">Тушь бывает пяти оттенков.</LhTabPane>
    <LhTabPane name="cinnabar" label="Киноварь" disabled>Киноварь использовать нельзя.</LhTabPane>
    <LhTabPane name="gold" label="Золото">Точечная роспись gamboge.</LhTabPane>
  </LhTabs>
</template>
vue
<script>
export default {}
</script>

<template>
  <LhTabs type="card">
    <LhTabPane name="ink" label="Тушь">Тушь бывает пяти оттенков.</LhTabPane>
    <LhTabPane name="cinnabar" label="Киноварь" disabled>Киноварь использовать нельзя.</LhTabPane>
    <LhTabPane name="gold" label="Золото">Точечная роспись gamboge.</LhTabPane>
  </LhTabs>
</template>

Положение снизу ​

Положение снизу
Монументальность горного рельефа.
vue
<script setup lang="ts">
</script>

<template>
  <LhTabs tab-position="bottom">
    <LhTabPane name="mountain" label="Гора">Монументальность горного рельефа.</LhTabPane>
    <LhTabPane name="water" label="Вода">Воздушная лёгкость водной стихии.</LhTabPane>
  </LhTabs>
</template>
vue
<script>
export default {}
</script>

<template>
  <LhTabs tab-position="bottom">
    <LhTabPane name="mountain" label="Гора">Монументальность горного рельефа.</LhTabPane>
    <LhTabPane name="water" label="Вода">Воздушная лёгкость водной стихии.</LhTabPane>
  </LhTabs>
</template>

Закрытие и добавление ​

Закрытие и добавление
Содержимое первого свитка.
vue
<script setup lang="ts">
import { ref } from 'vue'
const panes = ref([
  { name: 's1', label: 'Свиток 1', content: 'Содержимое первого свитка.', disabled: false },
  { name: 's2', label: 'Свиток 2', content: 'Содержимое второго свитка.', disabled: false },
])
let index = 2

const removePane = (name) => {
  const target = panes.value.find((pane) => pane.name === name)
  if (target) panes.value.splice(panes.value.indexOf(target), 1)
}
const addPane = () => {
  index += 1
  panes.value.push({ name: `s${index}`, label: `Свиток ${index}`, content: 'Содержимое нового свитка.', disabled: false })
}
</script>

<template>
  <!-- Закрытие и добавление -->
  <LhTabs closable addable tab-position="bottom" @tab-remove="removePane" @tab-add="addPane">
    <LhTabPane
      v-for="pane in panes"
      :key="pane.name"
      :name="pane.name"
      :label="pane.label"
      :disabled="pane.disabled"
    >{{ pane.content }}</LhTabPane>
  </LhTabs>
</template>
vue
<script>
export default {
  data() {
    return {
      panes: [
        { name: 's1', label: 'Свиток 1', content: 'Содержимое первого свитка.', disabled: false },
        { name: 's2', label: 'Свиток 2', content: 'Содержимое второго свитка.', disabled: false },
      ],
      index: 2,
    }
  },
  methods: {
    removePane(name) {
      const target = this.panes.find((pane) => pane.name === name)
      if (target) this.panes.splice(this.panes.indexOf(target), 1)
    },
    addPane() {
      this.index += 1
      this.panes.push({ name: `s${this.index}`, label: `Свиток ${this.index}`, content: 'Содержимое нового свитка.', disabled: false })
    },
  },
}
</script>

<template>
  <!-- Закрытие и добавление -->
  <LhTabs closable addable tab-position="bottom" @tab-remove="removePane" @tab-add="addPane">
    <LhTabPane
      v-for="pane in panes"
      :key="pane.name"
      :name="pane.name"
      :label="pane.label"
      :disabled="pane.disabled"
    >{{ pane.content }}</LhTabPane>
  </LhTabs>
</template>

При закрытии активной вкладки компонент автоматически переключается на соседнюю доступную вкладку и генерирует tab-remove; удаление соответствующей pane из источника данных остается за пользователем компонента.

Управляемое использование ​

Управляемое использование
Содержимое в стиле туши.

Текущая вкладка: mo

vue
<script setup lang="ts">
import { ref } from 'vue'
const active = ref('mo')
</script>

<template>
  <LhTabs v-model="active" type="card">
    <LhTabPane name="zh" label="Китайский стиль">Содержимое в китайском стиле.</LhTabPane>
    <LhTabPane name="mo" label="Тушь">Содержимое в стиле туши.</LhTabPane>
  </LhTabs>
</template>
vue
<script>
export default {
  data() {
    return { active: 'mo' }
  },
}
</script>

<template>
  <LhTabs v-model="active" type="card">
    <LhTabPane name="zh" label="Китайский стиль">Содержимое в китайском стиле.</LhTabPane>
    <LhTabPane name="mo" label="Тушь">Содержимое в стиле туши.</LhTabPane>
  </LhTabs>
</template>

Tabs API ​

LhTabs Props ​

СвойствоОписаниеТипПо умолчанию
modelValueИмя активной вкладки (v-model)string—
typeВнешний вид"line" | "card"'line'
closableМожно ли закрывать вкладкиbooleanfalse
addableПоказывать ли кнопку добавленияbooleanfalse
tabPositionПоложение вкладок"top" | "bottom"'top'
sxСвойство sx для быстрой вёрсткиLhSxProps—

LhTabs События ​

СобытиеОписаниеПараметры обратного вызова
update:modelValueИзменение активной вкладки (v-model)(name: string)
tab-changeИзменение активной вкладки(name: string)
tab-removeЗакрытие вкладки(name: string)
tab-addКлик по кнопке добавления—

LhTabPane Props ​

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

Слоты ​

СлотОписаниеКомпонент
defaultПанели вкладок (список LhTabPane)LhTabs
defaultСодержимое панелиLhTabPane

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

Строго следует шаблону вкладок WAI-ARIA APG:

  • Заголовки вкладок имеют role="tablist", каждая вкладка — role="tab" (aria-selected + aria-controls), панель — role="tabpanel" (aria-labelledby + tabindex="0")
  • roving tabindex: фокус по Tab доступен только активной вкладке, остальные имеют tabindex="-1"
  • Стрелки перемещают по доступным вкладкам и автоматически активируют их (пропуская отключённые), Home/End — переход к первой/последней
  • При closable закрытие активной вкладки выполняется клавишей Delete; значок закрытия является декоративным элементом aria-hidden, с клавиатуры используется Delete, чтобы избежать вложенных кнопок
  • Отключённые вкладки не могут получать фокус и активироваться; операции tab-remove и другие не действуют на отключённые элементы

Определения типов ​

Компонент экспортирует следующие структуры TypeScript (автоматически извлечено из исходников packages/components/tabs/src/types.ts и @lh-ui/share/core/*; раскройте каждый пункт, чтобы увидеть полное определение; описания свойств — в таблице Props выше):

LhTabsProps
ts
export interface LhTabsProps {
  /** Имя активной вкладки (v-model) */
  modelValue?: string
  /** Внешний вид */
  type?: LhTabsType
  /** Можно ли закрывать вкладки */
  closable?: boolean
  /** Показывать ли кнопку добавления */
  addable?: boolean
  /** Положение вкладок */
  tabPosition?: LhTabsPosition
  /** Свойство sx для быстрой вёрстки */
  sx?: LhSxProps
}
LhTabPaneProps
ts
export interface LhTabPaneProps {
  /** Уникальный идентификатор вкладки (стабильный ключ; динамически изменять не рекомендуется) */
  name: string
  /** Заголовок вкладки */
  label?: string
  /** Отключить вкладку */
  disabled?: boolean
}
LhTabsType (из @lh-ui/share/core/tabs)
ts
/**
 * Внешний вид вкладок
 */
export type LhTabsType = 'line' | 'card'
LhTabsPosition (из @lh-ui/share/core/tabs)
ts
/**
 * Положение вкладок
 */
export type LhTabsPosition = 'top' | 'bottom'

Красота традиций — основа кода