Fil d’ariane - DsfrBreadcrumb
🌟 Introduction
Bienvenue à la documentation du composant DsfrBreadcrumb ! Ce composant est un véritable GPS pour vos interfaces utilisateur, guidant les utilisateurs à travers les différents niveaux de votre application avec aisance et élégance. Utilisons TypeScript et Vue pour explorer ses fonctionnalités.
Le fil d’Ariane est un système de navigation secondaire qui permet à l’utilisateur de se situer sur le site qu’il consulte.
🏅 La documentation sur le fil d’Ariane sur le DSFR
La story sur le fil d’Ariane sur le storybook de VueDsfr📐 Structure
Dans l’ordre, il se compose des éléments suivants :
- un lien menant à la racine du site (page d’accueil) - obligatoire ;
- des liens vers les pages séparant la racine du site de la page courante - obligatoire si la hiérarchie du site comporte plus d’un niveau ;
- la page courante, seul élément non cliquable - obligatoire.
🛠️ Props
Nom | Type | Défaut | Description |
---|---|---|---|
breadcrumbId | String | () => getRandomId('breadcrumb') | Identifiant unique pour le composant breadcrumb, généré automatiquement pour assurer l'accessibilité. |
links | Array | () => [{ text: '' }] | Un tableau d'objets représentant les liens dans le fil d'Ariane. Chaque objet peut avoir une propriété 'text' et, optionnellement, 'to' pour les routes. |
navigationLabel | String | 'vous êtes ici :' | Label affiché sur la balise nav du fil d’Ariane. |
showBreadcrumbLabel | String | 'Voir le fil d’Ariane' | Label du bouton d'affichage du fil d’Ariane. |
📡 Évenements
Ce composant n'émet pas directement d'événements, mais vous pouvez écouter les événements de clic sur les liens individuels si nécessaire.
🧩 Slots
Pas de slots définis pour DsfrBreadcrumb
. Le contenu est entièrement géré via les props.
📝 Exemples
Voici un exemple d'utilisation de DsfrBreadcrumb :
<DsfrBreadcrumb
breadcrumbId="mon-fil-dariane"
:links="[
{ text: 'Accueil', to: '/' },
{ text: 'Bibliothèque', to: '/bibliotheque' },
{ text: 'Livre', to: '/livre' }
{ text: 'Le Seigneur des anneaux' }
]"
/>
<script lang="ts" setup>
import { getCurrentInstance } from 'vue'
import { createRouter, createWebHistory } from 'vue-router'
import DsfrBreadcrumb from '../DsfrBreadcrumb.vue'
const app = getCurrentInstance()
app?.appContext.app.use(
createRouter({
history: createWebHistory(),
routes: [
{ path: '/', component: { template: '<div>Accueil</div>' } },
{ path: '/bibliotheque', component: { template: '<div>Bibliothèque</div>' } },
{ path: '/livre', component: { template: '<div>Livre</div>' } },
],
}),
)
</script>
<template>
<div class="fr-container fr-my-2v">
<DsfrBreadcrumb
breadcrumb-id="mon-fil-dariane"
:links="[
{ text: 'Accueil', to: '/' },
{ text: 'Bibliothèque', to: '/bibliotheque' },
{ text: 'Livre', to: '/livre' },
{ text: 'Le Seigneur des anneaux' },
]"
/>
</div>
</template>
<script setup lang="ts">
import { ref, watch } from 'vue'
import { useCollapsable } from '../../composables'
import { getRandomId } from '../../utils/random-utils'
import type { DsfrBreadcrumbProps } from './DsfrBreadcrumb.types'
export type { DsfrBreadcrumbProps }
withDefaults(defineProps<DsfrBreadcrumbProps>(), {
breadcrumbId: () => getRandomId('breadcrumb'),
links: () => [{ text: '' }],
navigationLabel: 'vous êtes ici :',
showBreadcrumbLabel: 'Voir le fil d’Ariane',
})
const {
collapse,
collapsing,
cssExpanded,
doExpand,
onTransitionEnd,
} = useCollapsable()
const expanded = ref(false)
watch(expanded, (newValue, oldValue) => {
if (newValue !== oldValue) {
/*
* @see https://github.com/GouvernementFR/dsfr/blob/main/src/core/script/collapse/collapse.js
*/
doExpand(newValue)
}
})
</script>
<template>
<nav
role="navigation"
class="fr-breadcrumb"
:aria-label="navigationLabel"
>
<button
v-show="!expanded"
class="fr-breadcrumb__button"
:aria-expanded="expanded"
:aria-controls="breadcrumbId"
@click="expanded = !expanded"
>
{{ showBreadcrumbLabel }}
</button>
<div
:id="breadcrumbId"
ref="collapse"
class="fr-collapse"
:class="{
'fr-collapse--expanded': cssExpanded, // Need to use a separate data to add/remove the class after a RAF
'fr-collapsing': collapsing,
}"
@transitionend="onTransitionEnd(expanded)"
>
<ol class="fr-breadcrumb__list">
<li
v-for="(link, index) in links"
:key="index"
class="fr-breadcrumb__item"
data-testid="lis"
>
<RouterLink
v-if="link.to"
class="fr-breadcrumb__link"
:to="link.to"
:aria-current="index === links.length - 1 ? 'page' : undefined"
>
{{ link.text }}
</RouterLink>
<a
v-if="!link.to"
class="fr-breadcrumb__link"
:aria-current="index === links.length - 1 ? 'page' : undefined"
>{{ link.text }}</a>
</li>
</ol>
</div>
</nav>
</template>
Note :
Sur un écran plus large, le fil d’Ariane apparaîtrait directement en entier, sans le lien "Voir le fil d’Ariane"