@amsom-habitat/nav-tabs
v1.2.1
Published
Deux composants Vue 3 de navigation par onglets : **vertical** (nav à gauche, contenu à droite) et **horizontal** (nav en haut, contenu en dessous).
Downloads
502
Readme
@amsom-habitat/nav-tabs
Deux composants Vue 3 de navigation par onglets : vertical (nav à gauche, contenu à droite) et horizontal (nav en haut, contenu en dessous).
Installation
npm install @amsom-habitat/nav-tabsimport { AmsomNavTabsVertical, AmsomNavTabsHorizontal } from '@amsom-habitat/nav-tabs'Nécessite Bootstrap 5 (@amsom-habitat/bootstrap-5) dans le projet consommateur.
AmsomNavTabsVertical
Usage minimal
<amsom-nav-tabs-vertical v-model="selected" :items="items" item-key="id" item-label="label">
<template #content>
<div class="p-3">Contenu pour l'onglet {{ selected }}</div>
</template>
</amsom-nav-tabs-vertical>Props
Données
| Prop | Type | Défaut | Description |
|------|------|--------|-------------|
| items | Array | — (requis) | Liste des items à afficher |
| modelValue (v-model) | String \| Number \| Object | null | Clé de l'onglet sélectionné |
| itemKey | String | 'id' | Propriété de l'item utilisée comme clé |
| itemLabel | String \| Function | 'label' | Propriété ou fonction (item) => string pour le libellé |
| itemDisabled | String \| Function | null | Propriété ou fonction (item) => boolean pour désactiver un item |
Colonne nav
| Prop | Type | Défaut | Description |
|------|------|--------|-------------|
| navWidth | 'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl' | 'md' | Largeur prédéfinie : xs=80px sm=120px md=180px lg=240px xl=320px |
| navMinWidth | String | null | Largeur minimale. Ex : '150px' |
| navMaxWidth | String | null | Largeur maximale. Prend le dessus sur navWidth. |
| navAlign | 'start' \| 'center' \| 'end' | 'start' | Alignement vertical de la liste des onglets |
Hauteur
| Prop | Type | Défaut | Description |
|------|------|--------|-------------|
| maxHeight | String | null | Hauteur max commune à la nav ET au contenu. Chaque colonne scrolle indépendamment. Ex : '70vh' |
| navMaxHeight | String | null | Hauteur max de la seule colonne nav (onglets de gauche), qui scrolle si dépassement. Prend le dessus sur maxHeight pour la nav, sans impacter le contenu. Utile quand beaucoup d'onglets feraient grandir une modale. Ex : '30vh' |
| contentHeight | String | null | Hauteur explicite du contenu (nécessaire pour que h-100 fonctionne dans #content). Ex : '500px' |
| contentMinHeight | String | null | Hauteur minimale du contenu. Ex : '200px' |
Onglets
| Prop | Type | Défaut | Description |
|------|------|--------|-------------|
| tabSize | 'none' \| 'xs' \| 'sm' \| 'md' \| 'lg' \| 'xl' | 'md' | Padding + taille de police. 'none' = aucune classe (gérer dans le slot) |
| tabSpacing | 0–5 | 2 | Espacement entre onglets (Bootstrap gap-*) |
| overflow | 'ellipsis' \| 'clip' \| 'wrap' | 'ellipsis' | Comportement du texte trop long dans le slot #libelle par défaut |
| tabClass | String \| Array \| Object \| Function | 'rounded-start' | Classes sur le wrapper bordure de chaque onglet. Accepte une fonction (item) => string |
| activeClass | String \| Array \| Object \| Function | 'bg-white text-primary' | Classes de l'onglet actif |
| inactiveClass | String \| Array \| Object \| Function | 'bg-gray text-secondary' | Classes des onglets inactifs |
| tabMinWidth | String | null | Largeur minimale de chaque onglet |
| tabMaxWidth | String | null | Largeur maximale de chaque onglet |
| tabMinHeight | String | null | Hauteur minimale de chaque onglet |
| tabMaxHeight | String | null | Hauteur maximale de chaque onglet |
Zone contenu
| Prop | Type | Défaut | Description |
|------|------|--------|-------------|
| contentMinWidth | String | null | Largeur minimale du contenu |
| contentMaxWidth | String | null | Largeur maximale du contenu |
| contentClass | String \| Array \| Object | null | Classes CSS supplémentaires sur la zone contenu |
Slots
La hiérarchie des slots permet de choisir le niveau de personnalisation souhaité :
Wrapper bordure + actif/inactif (tabClass, activeClass, inactiveClass)
└── #nav → brut, aucun padding — accès à : item, selected, disabled
└── Wrapper taille (tabSize)
└── #nav-libelle → remplace badge+libelle — accès à : item, selected, disabled
├── #badge → avant le libellé — accès à : item
└── #libelle → libellé seul — accès à : item
#content → zone contenu à droite| Slot | Props exposés | Quand l'utiliser |
|------|--------------|-----------------|
| #nav | item, selected, disabled | Layout entièrement libre à l'intérieur des bordures. Les couleurs actif/inactif et les bordures sont gérées par le composant. |
| #nav-libelle | item, selected, disabled | Remplacer badge+libelle en un bloc tout en conservant le padding/taille géré par tabSize. |
| #badge | item | Ajouter un badge avant le libellé (compteur, icône…). |
| #libelle | item | Personnaliser uniquement le libellé. Utiliser avec tab-size="none" pour gérer soi-même le padding. |
| #content | — | Zone de contenu principale à droite. |
Exemples
Hauteur contrainte avec scroll indépendant
<amsom-nav-tabs-vertical
v-model="selected"
:items="items"
max-height="70vh"
content-height="70vh"
>
<template #content>
<div class="h-100 overflow-auto p-3">...</div>
</template>
</amsom-nav-tabs-vertical>Slot #nav — icônes + texte, layout libre
<amsom-nav-tabs-vertical v-model="selected" :items="items">
<template #nav="{ item, selected }">
<div class="d-flex align-items-center gap-2 px-3 py-2">
<font-awesome-icon :icon="item.icon" />
<span>{{ item.label }}</span>
</div>
</template>
</amsom-nav-tabs-vertical>Slot #nav-libelle — libellé + métadonnée sur une ligne
<amsom-nav-tabs-vertical v-model="selected" :items="pieces">
<template #nav-libelle="{ item }">
<span class="d-flex justify-content-between w-100 gap-2">
<span class="text-wrap">{{ item.label }}</span>
<span class="text-muted fs-7">{{ item.surface }}</span>
</span>
</template>
</amsom-nav-tabs-vertical>Slot #libelle avec tab-size="none" — padding libre
<amsom-nav-tabs-vertical v-model="selected" :items="items" tab-size="none">
<template #libelle="{ item }">
<span class="d-flex justify-content-between w-100 gap-2 ps-3 py-1">
<span class="text-wrap">{{ item.label }}</span>
<span class="fs-7">{{ item.surface }}</span>
</span>
</template>
</amsom-nav-tabs-vertical>Classes dynamiques par item
<amsom-nav-tabs-vertical
v-model="selected"
:items="items"
:active-class="(item) => `bg-${item.variant} text-white`"
:inactive-class="(item) => `bg-${item.variant}-subtle text-${item.variant}`"
/>AmsomNavTabsHorizontal
Usage minimal
<amsom-nav-tabs-horizontal v-model="selected" :items="items" item-key="id" item-label="label">
<template #content>
<p>Contenu pour l'onglet {{ selected }}</p>
</template>
</amsom-nav-tabs-horizontal>Props
Données
Identiques à AmsomNavTabsVertical : items, modelValue, itemKey, itemLabel, itemDisabled.
Nav horizontale
| Prop | Type | Défaut | Description |
|------|------|--------|-------------|
| justify | 'start' \| 'center' \| 'end' \| 'between' \| 'around' \| 'evenly' | 'start' | Justification des onglets dans la barre |
Onglets
Identiques à AmsomNavTabsVertical : tabSize, overflow, tabClass, activeClass, inactiveClass, tabMinWidth, tabMaxWidth, tabMinHeight, tabMaxHeight.
Note :
overflown'est actif que sitabMaxWidthest défini. La barre elle-même scrolle toujours horizontalement si les onglets dépassent.
Zone contenu
| Prop | Type | Défaut | Description |
|------|------|--------|-------------|
| contentClass | String \| Array \| Object | null | Classes CSS supplémentaires sur la zone contenu |
| contentStyle | String \| Object | null | Style inline sur la zone contenu. Ex : 'max-height: 400px; overflow-y: auto' |
Slots
Même hiérarchie que le composant vertical :
| Slot | Props exposés | Description |
|------|--------------|-------------|
| #nav | item, selected, disabled | Layout libre dans les bordures |
| #nav-libelle | item, selected, disabled | Remplace badge+libelle en conservant tabSize |
| #badge | item | Badge avant le libellé |
| #libelle | item | Libellé seul |
| #content | — | Zone de contenu principale |
