Pestañas
Componente de pestañas; admite uso controlado / no controlado, dos aspectos (tarjeta / línea), cierre y adición de pestañas, y navegación completa por teclado.
Uso básico
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="Tinta">
Tinta difuminada, viva y fluida.
</LhTabPane>
<LhTabPane name="danqing" label="Danqing">
Colores danqing, resplandor de oro y verde.
</LhTabPane>
</LhTabs>
)
}
Props de Tabs
| Prop | Descripción | Tipo | Opciones | Predeterminado |
|---|---|---|---|---|
| value | Nombre de la pestaña activa (controlado) | string | — | — |
| defaultValue | Nombre de la pestaña activa (valor predeterminado no controlado) | string | — | — |
| type | Aspecto | 'line' | 'card' | — | 'line' |
| closable | Si las pestañas se pueden cerrar | boolean | — | false |
| addable | Si se muestra el botón de añadir | boolean | — | false |
| tabPosition | Posición de las pestañas | 'top' | 'bottom' | — | 'top' |
| sx | Propiedad abreviada de diseño | SxProps | — | — |
Props de TabPane
| Prop | Descripción | Tipo | Predeterminado |
|---|---|---|---|
| name | Identificador único de la pestaña (actúa como clave estable; no se recomienda modificarlo dinámicamente) | string | — |
| label | Título de la pestaña | ReactNode | — |
| disabled | Si está desactivada | boolean | false |
| children | Contenido de la pestaña | ReactNode | — |
Eventos de Tabs
| Evento | Descripción | Firma del callback | Equivalente en Vue |
|---|---|---|---|
| onChange | Se dispara cuando cambia la pestaña activa | (name: string) => void | @change |
| onRemove | Se dispara al cerrar una pestaña (la visibilidad de la pestaña la controla el lado de la aplicación) | (name: string) => void | @remove |
| onAdd | Se dispara al hacer clic en el botón de añadir | () => void | @add |
Pasar value es modo controlado; pasar defaultValue usa el estado interno no controlado. onChange se dispara en ambos modos. Al cerrar la pestaña activa, el modo no controlado conmuta automáticamente a la pestaña disponible adyacente (alineado con getNameAfterRemove de plus); en modo controlado lo gestiona el lado de la aplicación dentro de onRemove.
children deben ser directamente LhTabPane (se pueden renderizar con .map y se pueden envolver en un Fragment, pero no en un componente personalizado): el componente padre recorre los hijos con Children.forEach para recoger los registros de las pestañas, y una envoltura personalizada haría fallar la recolección.
Interacción de teclado
Sigue el patrón tabs de APG: cuando el foco está en un botón de pestaña, ArrowRight / ArrowLeft (en vertical, ArrowDown / ArrowUp) se desplazan entre las pestañas disponibles y las activan, saltando las desactivadas; Home / End saltan al primero / último elemento; Delete / Backspace cierran la pestaña actual (requiere closable). Solo la pestaña activa tiene tabindex=0; las demás, -1 (roving tabindex).
Accesibilidad
La barra de pestañas es role="tablist", las pestañas son role="tab" con aria-selected / aria-controls, y los paneles son role="tabpanel" con aria-labelledby; los ids se generan con useId() y son estables en SSR. Los paneles inactivos se sacan del árbol de accesibilidad con el atributo hidden.
ref
forwardRef<HTMLDivElement> — elemento raíz. LhTabPane reenvía HTMLDivElement.
Estilos
import '@lh-ui/react/theme.css'
import '@lh-ui/react/style/tabs'