Onglets
Basculement de contenu de même niveau. Conformité stricte au modèle tabs de WAI-ARIA APG : association des trois rôles tablist / tab / tabpanel + roving tabindex + navigation par flèches.
Utilisation de base
<script setup lang="ts">
</script>
<template>
<LhTabs>
<LhTabPane name="prose" label="Prose">Contenu de prose lavis.</LhTabPane>
<LhTabPane name="poem" label="Poésie">Contenu des règles poétiques.</LhTabPane>
<LhTabPane name="calligraphy" label="Calligraphie">Contenu de calligraphie et de stèles.</LhTabPane>
</LhTabs>
</template><script>
export default {}
</script>
<template>
<LhTabs>
<LhTabPane name="prose" label="Prose">Contenu de prose lavis.</LhTabPane>
<LhTabPane name="poem" label="Poésie">Contenu des règles poétiques.</LhTabPane>
<LhTabPane name="calligraphy" label="Calligraphie">Contenu de calligraphie et de stèles.</LhTabPane>
</LhTabs>
</template>Aspect carte et désactivation
<script setup lang="ts">
</script>
<template>
<LhTabs type="card">
<LhTabPane name="ink" label="Encre">L'encre offre cinq nuances.</LhTabPane>
<LhTabPane name="cinnabar" label="Vermillon" disabled>Le cinabre est indisponible.</LhTabPane>
<LhTabPane name="gold" label="Or">Rehaussé de jaune gamboge.</LhTabPane>
</LhTabs>
</template><script>
export default {}
</script>
<template>
<LhTabs type="card">
<LhTabPane name="ink" label="Encre">L'encre offre cinq nuances.</LhTabPane>
<LhTabPane name="cinnabar" label="Vermillon" disabled>Le cinabre est indisponible.</LhTabPane>
<LhTabPane name="gold" label="Or">Rehaussé de jaune gamboge.</LhTabPane>
</LhTabs>
</template>Position en bas
<script setup lang="ts">
</script>
<template>
<LhTabs tab-position="bottom">
<LhTabPane name="mountain" label="Montagne">Les reliefs sont majestueux.</LhTabPane>
<LhTabPane name="water" label="Eau">L'esprit de l'eau est éthéré.</LhTabPane>
</LhTabs>
</template><script>
export default {}
</script>
<template>
<LhTabs tab-position="bottom">
<LhTabPane name="mountain" label="Montagne">Les reliefs sont majestueux.</LhTabPane>
<LhTabPane name="water" label="Eau">L'esprit de l'eau est éthéré.</LhTabPane>
</LhTabs>
</template>Fermeture et ajout
<script setup lang="ts">
import { ref } from 'vue'
const panes = ref([
{ name: 's1', label: 'Rouleau 1', content: 'Contenu du premier rouleau.', disabled: false },
{ name: 's2', label: 'Rouleau 2', content: 'Contenu du deuxième rouleau.', 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: `Rouleau ${index}`, content: 'Contenu du nouveau rouleau.', disabled: false })
}
</script>
<template>
<!-- Fermeture et ajout -->
<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><script>
export default {
data() {
return {
panes: [
{ name: 's1', label: 'Rouleau 1', content: 'Contenu du premier rouleau.', disabled: false },
{ name: 's2', label: 'Rouleau 2', content: 'Contenu du deuxième rouleau.', 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: `Rouleau ${this.index}`, content: 'Contenu du nouveau rouleau.', disabled: false })
},
},
}
</script>
<template>
<!-- Fermeture et ajout -->
<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>Lors de la fermeture de l'onglet actif, le composant bascule automatiquement sur l'onglet adjacent disponible et émet
tab-remove; la suppression du panneau correspondant de la source de données incombe à l'utilisateur du composant.
Usage contrôlé
Onglet actuel : mo
<script setup lang="ts">
import { ref } from 'vue'
const active = ref('mo')
</script>
<template>
<LhTabs v-model="active" type="card">
<LhTabPane name="zh" label="Style Guofeng">Contenu du style Guofeng.</LhTabPane>
<LhTabPane name="mo" label="Lavis">Contenu lavis.</LhTabPane>
</LhTabs>
</template><script>
export default {
data() {
return { active: 'mo' }
},
}
</script>
<template>
<LhTabs v-model="active" type="card">
<LhTabPane name="zh" label="Style Guofeng">Contenu du style Guofeng.</LhTabPane>
<LhTabPane name="mo" label="Lavis">Contenu lavis.</LhTabPane>
</LhTabs>
</template>API Tabs
LhTabs Props
| Prop | Description | Type | Valeur par défaut |
|---|---|---|---|
| modelValue | Name de l'onglet actuellement actif (v-model) | string | — |
| type | Aspect | "line" | "card" | 'line' |
| closable | Les onglets sont fermables | boolean | false |
| addable | Afficher ou non le bouton d'ajout | boolean | false |
| tabPosition | Position des onglets | "top" | "bottom" | 'top' |
| sx | Props de mise en page sx | LhSxProps | — |
LhTabs Events
| Événement | Description | Paramètre |
|---|---|---|
| update:modelValue | L'onglet actif change (v-model) | (name: string) |
| tab-change | L'onglet actif change | (name: string) |
| tab-remove | Un onglet est fermé | (name: string) |
| tab-add | Clic sur le bouton d'ajout | — |
LhTabPane Props
| Prop | Description | Type | Valeur par défaut |
|---|---|---|---|
| name | Identifiant unique de l'onglet (clé stable, sa modification dynamique est déconseillée) | string | — |
| label | Titre de l'onglet | string | '' |
| disabled | Désactivé ou non | boolean | false |
Slots
| Slot | Description | Composant concerné |
|---|---|---|
| default | Panneau d'onglets (liste de LhTabPane) | LhTabs |
| default | Contenu du panneau | LhTabPane |
Accessibilité
Conformité stricte au modèle tabs de WAI-ARIA APG :
- L'en-tête des onglets a
role="tablist", chaque onglet arole="tab"(aria-selected+aria-controls), et le panneau arole="tabpanel"(aria-labelledby+tabindex="0") - Roving tabindex : seul l'onglet actif peut recevoir le focus via Tab, les autres ont
tabindex="-1" - Les flèches se déplacent entre les onglets disponibles et les activent automatiquement (en sautant les éléments désactivés) ; les touches Origine/Fin vont au premier ou au dernier onglet
- Lorsque
closableest activé, la touche Suppr ferme l'onglet courant ; l'icône de fermeture est décorative (aria-hidden), la fermeture clavier passe par Suppr afin d'éviter d'imbriquer des boutons - Les onglets désactivés ne peuvent être focalisés ni activés ;
tab-removeet les autres opérations sont sans effet sur les éléments désactivés
Définitions de types
Ce composant exporte les structures de types TypeScript suivantes (extraites automatiquement de packages/components/tabs/src/types.ts et des sources @lh-ui/share/core/* ; cliquez sur chaque entrée pour déplier la définition complète ; la description des props se trouve dans le tableau Props ci-dessus) :
LhTabsProps
export interface LhTabsProps {
/** Name de l'onglet actuellement actif (v-model) */
modelValue?: string
/** Aspect */
type?: LhTabsType
/** Les onglets sont fermables */
closable?: boolean
/** Afficher ou non le bouton d'ajout */
addable?: boolean
/** Position des onglets */
tabPosition?: LhTabsPosition
/** Props de mise en page sx */
sx?: LhSxProps
}LhTabPaneProps
export interface LhTabPaneProps {
/** Identifiant unique de l'onglet (clé stable, sa modification dynamique est déconseillée) */
name: string
/** Titre de l'onglet */
label?: string
/** Désactivé ou non */
disabled?: boolean
}LhTabsType (provenant de @lh-ui/share/core/tabs)
/**
* Aspect des onglets
*/
export type LhTabsType = 'line' | 'card'LhTabsPosition (provenant de @lh-ui/share/core/tabs)
/**
* Position des onglets
*/
export type LhTabsPosition = 'top' | 'bottom'