Skip to content
API 风格:

Pestañas ​

Cambio de contenido del mismo nivel. Sigue de forma estricta el patrón de pestañas de WAI-ARIA APG: tres roles vinculados tablist/tab/tabpanel + roving tabindex + navegación con las teclas de dirección.

Uso básico ​

Uso básico
Contenido de prosa a tinta.
vue
<script setup lang="ts">
</script>

<template>
  <LhTabs>
    <LhTabPane name="prose" label="Prosa">Contenido de prosa a tinta.</LhTabPane>
    <LhTabPane name="poem" label="Poesía">Contenido de métrica poética.</LhTabPane>
    <LhTabPane name="calligraphy" label="Caligrafía">Contenido de caligrafía y lápidas.</LhTabPane>
  </LhTabs>
</template>
vue
<script>
export default {}
</script>

<template>
  <LhTabs>
    <LhTabPane name="prose" label="Prosa">Contenido de prosa a tinta.</LhTabPane>
    <LhTabPane name="poem" label="Poesía">Contenido de métrica poética.</LhTabPane>
    <LhTabPane name="calligraphy" label="Caligrafía">Contenido de caligrafía y lápidas.</LhTabPane>
  </LhTabs>
</template>

Aspecto de tarjeta y deshabilitado ​

Aspecto de tarjeta y deshabilitado
La tinta tiene cinco tonos.
vue
<script setup lang="ts">
</script>

<template>
  <LhTabs type="card">
    <LhTabPane name="ink" label="Tinta">La tinta tiene cinco tonos.</LhTabPane>
    <LhTabPane name="cinnabar" label="Bermellón" disabled>El cinabrio no se puede usar.</LhTabPane>
    <LhTabPane name="gold" label="Oro">Toques de amarillo reseda.</LhTabPane>
  </LhTabs>
</template>
vue
<script>
export default {}
</script>

<template>
  <LhTabs type="card">
    <LhTabPane name="ink" label="Tinta">La tinta tiene cinco tonos.</LhTabPane>
    <LhTabPane name="cinnabar" label="Bermellón" disabled>El cinabrio no se puede usar.</LhTabPane>
    <LhTabPane name="gold" label="Oro">Toques de amarillo reseda.</LhTabPane>
  </LhTabs>
</template>

Posición inferior ​

Posición inferior
La montaña tiene una robusta presencia.
vue
<script setup lang="ts">
</script>

<template>
  <LhTabs tab-position="bottom">
    <LhTabPane name="mountain" label="Montaña">La montaña tiene una robusta presencia.</LhTabPane>
    <LhTabPane name="water" label="Agua">El agua transmite un sentido de vacío y ligereza.</LhTabPane>
  </LhTabs>
</template>
vue
<script>
export default {}
</script>

<template>
  <LhTabs tab-position="bottom">
    <LhTabPane name="mountain" label="Montaña">La montaña tiene una robusta presencia.</LhTabPane>
    <LhTabPane name="water" label="Agua">El agua transmite un sentido de vacío y ligereza.</LhTabPane>
  </LhTabs>
</template>

Cerrable y añadir ​

Cerrable y añadir
Contenido del primer rollo.
vue
<script setup lang="ts">
import { ref } from 'vue'
const panes = ref([
  { name: 's1', label: 'Rollo de pintura 1', content: 'Contenido del primer rollo.', disabled: false },
  { name: 's2', label: 'Rollo de pintura 2', content: 'Contenido del segundo rollo.', 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: `Rollo de pintura ${index}`, content: 'Contenido del rollo nuevo.', disabled: false })
}
</script>

<template>
  <!-- Cerrable y añadir -->
  <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: 'Rollo de pintura 1', content: 'Contenido del primer rollo.', disabled: false },
        { name: 's2', label: 'Rollo de pintura 2', content: 'Contenido del segundo rollo.', 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: `Rollo de pintura ${this.index}`, content: 'Contenido del rollo nuevo.', disabled: false })
    },
  },
}
</script>

<template>
  <!-- Cerrable y añadir -->
  <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>

Al cerrar la pestaña activa, el componente conmuta de forma coordinada a la pestaña disponible adyacente y emite tab-remove; es responsabilidad de quien lo usa eliminar el pane correspondiente del origen de datos.

Uso controlado ​

Uso controlado
Contenido de tinta.

Pestaña actual: 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="Estilo nacional">Contenido de estilo nacional.</LhTabPane>
    <LhTabPane name="mo" label="Tinta">Contenido de tinta.</LhTabPane>
  </LhTabs>
</template>
vue
<script>
export default {
  data() {
    return { active: 'mo' }
  },
}
</script>

<template>
  <LhTabs v-model="active" type="card">
    <LhTabPane name="zh" label="Estilo nacional">Contenido de estilo nacional.</LhTabPane>
    <LhTabPane name="mo" label="Tinta">Contenido de tinta.</LhTabPane>
  </LhTabs>
</template>

Tabs API ​

LhTabs Props ​

PropDescripciónTipoPredeterminado
modelValuename de la pestaña activada actualmente (v-model)string—
typeAspecto"line" | "card"'line'
closableSi las pestañas se pueden cerrarbooleanfalse
addableSi se muestra el botón de añadirbooleanfalse
tabPositionPosición de las pestañas"top" | "bottom"'top'
sxProps de maquetación rápida sxLhSxProps—

LhTabs Events ​

EventoDescripciónParámetro
update:modelValueCambio de la pestaña activada (v-model)(name: string)
tab-changeCambio de la pestaña activada(name: string)
tab-removeCierre de una pestaña(name: string)
tab-addPulsación del botón de añadir—

LhTabPane Props ​

PropDescripciónTipoPredeterminado
nameIdentificador único de la pestaña (clave estable; no se recomienda modificarlo de forma dinámica)string—
labelTítulo de la pestañastring''
disabledSi se deshabilitabooleanfalse

Slots ​

SlotDescripciónComponente afín
defaultPaneles de pestaña (lista de LhTabPane)LhTabs
defaultContenido del panelLhTabPane

Accesibilidad ​

Sigue de forma estricta el patrón de pestañas de WAI-ARIA APG:

  • La cabecera de las pestañas es role="tablist", cada pestaña es role="tab" (aria-selected + aria-controls) y el panel es role="tabpanel" (aria-labelledby + tabindex="0")
  • Roving tabindex: solo la pestaña activada puede recibir el foco con Tab; las demás tienen tabindex="-1"
  • Las teclas de dirección se mueven entre las pestañas disponibles y las activan automáticamente (saltándose las deshabilitadas); Home/End salta al principio y al final
  • Con closable, la tecla Delete cierra la pestaña actual; el icono de cierre es decorativo (aria-hidden) y el teclado usa Delete, para evitar anidar un botón dentro de otro
  • Las pestañas deshabilitadas no se pueden enfocar ni activar; acciones como tab-remove no tienen efecto sobre los elementos deshabilitados

Definiciones de tipos ​

Las estructuras de tipos TypeScript que exporta este componente son las siguientes (extraídas automáticamente de packages/components/tabs/src/types.ts y del código fuente de @lh-ui/share/core/*; despliega cada entrada para ver la definición completa; la descripción de los atributos está en la tabla de Props de arriba):

LhTabsProps
ts
export interface LhTabsProps {
  /** name de la pestaña activada actualmente (v-model) */
  modelValue?: string
  /** Aspecto */
  type?: LhTabsType
  /** Si las pestañas se pueden cerrar */
  closable?: boolean
  /** Si se muestra el botón de añadir */
  addable?: boolean
  /** Posición de las pestañas */
  tabPosition?: LhTabsPosition
  /** Props de maquetación rápida sx */
  sx?: LhSxProps
}
LhTabPaneProps
ts
export interface LhTabPaneProps {
  /** Identificador único de la pestaña (clave estable; no se recomienda modificarlo de forma dinámica) */
  name: string
  /** Título de la pestaña */
  label?: string
  /** Si se deshabilita */
  disabled?: boolean
}
LhTabsType (de @lh-ui/share/core/tabs)
ts
/**
 * Aspecto de las pestañas
 */
export type LhTabsType = 'line' | 'card'
LhTabsPosition (de @lh-ui/share/core/tabs)
ts
/**
 * Posición de las pestañas
 */
export type LhTabsPosition = 'top' | 'bottom'

La belleza de la tradición, el cimiento del código