Navigation principale - DsfrNavigation
🌟 Introduction
Le composant DsfrNavigation
, est le système central de navigation au sein d’un site. Elle permet d’orienter aisément l’usager à travers l'application voire même jusqu'aux confins de la galaxie !
🛠️Props
Nom | Type | Défaut | Obligatoire | Description |
---|---|---|---|---|
id | string | () => useRandomId(...) | Identifiant unique pour la nav. Si non spécifié, un ID aléatoire est généré. | |
label | string | Menu principal | Nom associé à la navigation. Utile pour l'accessibilité. | |
navItems | array | () => [] | ✅ | Tableau contenant les liens ou sous menus accessibles depuis la navigation. |
📡Événements
Nom | Description |
---|---|
click | Événement émis au clic qui déclence l'ouverture ou la fermeture d'un menu. |
keydown | Événement émis en appuyant sur la touche "Echap" qui déclence lla fermeture d'un menu ouvert. |
🧩 Slots
Nom | Description |
---|---|
default | Slot par défaut pour le contenu de la navigation, il se trouve dans la balise <ul class="fr-nav__list"> . |
📝 Exemples
Exemple simple d'utilisation de DsfrNavigation
:
vue
<script lang="ts" setup>
import DsfrNavigation from '../DsfrNavigation.vue'
const navItemsDemo = [
{
to: '/accueil',
text: 'Accueil',
},
{
to: '/tableau-de-bord',
text: 'Tableau de bord',
},
{
to: '/historique',
text: 'Historique',
},
]
</script>
<template>
<DsfrNavigation
label="Menu principal démo"
:nav-items="navItemsDemo"
/>
</template>
⚙️ Code source du composant
vue
<script lang="ts" setup>
import { onMounted, onUnmounted, ref } from 'vue'
import { useRandomId } from '../../utils/random-utils'
import DsfrNavigationItem from './DsfrNavigationItem.vue'
import DsfrNavigationMegaMenu from './DsfrNavigationMegaMenu.vue'
import DsfrNavigationMenu from './DsfrNavigationMenu.vue'
import DsfrNavigationMenuLink from './DsfrNavigationMenuLink.vue'
import type {
DsfrNavigationMegaMenuProps,
DsfrNavigationMenuLinkProps,
DsfrNavigationMenuLinks,
DsfrNavigationMenuProps,
DsfrNavigationProps,
} from './DsfrNavigation.types'
export type { DsfrNavigationMenuLinks, DsfrNavigationProps }
const props = withDefaults(defineProps<DsfrNavigationProps>(), {
id: () => useRandomId('nav'),
label: 'Menu principal',
navItems: () => [],
})
const expandedMenuId = ref<string | undefined>(undefined)
const toggle = (id: string | undefined) => {
if (id === expandedMenuId.value) {
expandedMenuId.value = undefined
return
}
expandedMenuId.value = id
}
const handleElementClick = (el: HTMLElement) => {
if (el === document.getElementById(props.id)) {
return
}
if (!el?.parentNode) {
toggle(expandedMenuId.value)
return
}
handleElementClick(el.parentNode as HTMLElement)
}
const onDocumentClick = (e: MouseEvent) => {
handleElementClick(e.target as HTMLElement)
}
const onKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Escape') {
toggle(expandedMenuId.value)
}
}
onMounted(() => {
document.addEventListener('click', onDocumentClick)
document.addEventListener('keydown', onKeyDown)
})
onUnmounted(() => {
document.removeEventListener('click', onDocumentClick)
document.removeEventListener('keydown', onKeyDown)
})
</script>
<template>
<nav
:id="id"
class="fr-nav"
role="navigation"
:aria-label="label"
>
<ul class="fr-nav__list">
<!-- @slot Slot par défaut pour le contenu de la liste. Sera dans `<ul class="fr-nav__list">` -->
<slot />
<DsfrNavigationItem
v-for="(navItem, idx) of navItems"
:id="navItem.id"
:key="idx"
>
<DsfrNavigationMenuLink
v-if="(navItem as DsfrNavigationMenuLinkProps).to && (navItem as DsfrNavigationMenuLinkProps).text"
v-bind="navItem"
:expanded-id="expandedMenuId"
@toggle-id="toggle($event)"
/>
<!-- @vue-ignore -->
<DsfrNavigationMenu
v-else-if="(navItem as DsfrNavigationMenuProps).title && (navItem as DsfrNavigationMenuProps).links"
v-bind="(navItem as DsfrNavigationMenuProps)"
:expanded-id="expandedMenuId"
@toggle-id="toggle($event)"
/>
<!-- @vue-ignore -->
<DsfrNavigationMegaMenu
v-else-if="(navItem as DsfrNavigationMegaMenuProps).title && (navItem as DsfrNavigationMegaMenuProps).menus"
v-bind="(navItem as DsfrNavigationMegaMenuProps)"
:expanded-id="expandedMenuId"
@toggle-id="toggle($event)"
/>
</DsfrNavigationItem>
</ul>
</nav>
</template>
<style>
.fr-nav__list {
position: relative;
}
</style>
ts
import type { RouteLocationRaw } from 'vue-router'
export type DsfrNavigationMenuLinkProps = {
id?: string
to?: string | RouteLocationRaw
text?: string
icon?: string
onClick?: ($event: MouseEvent) => void
}
export type DsfrNavigationMenuItemProps = {
id?: string
active?: boolean
}
export type DsfrNavigationMenuProps = {
id?: string
title: string
links?: DsfrNavigationMenuLinkProps[]
expandedId?: string
active?: boolean
}
export type DsfrNavigationItemProps = {
id?: string
active?: boolean
}
export type DsfrNavigationMegaMenuCategoryProps = {
title: string
active?: boolean
links: DsfrNavigationMenuLinkProps[]
}
export type DsfrNavigationMegaMenuProps = {
id?: string
title: string
description?: string
link?: { to: RouteLocationRaw, text: string }
menus?: DsfrNavigationMegaMenuCategoryProps[]
expandedId?: string
active?: boolean
}
export type DsfrNavigationMenuLinks = (DsfrNavigationMenuLinkProps | DsfrNavigationMegaMenuProps | DsfrNavigationMenuProps)[]
export type DsfrNavigationProps = {
id?: string
label?: string
navItems: (
DsfrNavigationMenuLinkProps
| DsfrNavigationMenuProps
| DsfrNavigationMegaMenuProps
)[]
}
Avec DsfrNavigation
, toute destination est à portée de clic, Bon voyage !