Lien de menu de navigation - DsfrNavigationMenuLink
🌟 Introduction
Le lien de menu de navigation est un composant qui crée un lien cliquable dans un menu de navigation. Il gère automatiquement les liens externes et internes avec le routeur Vue.
Le composant DsfrNavigationMenuLink
crée un lien de navigation avec support des icônes, gestion automatique des liens externes/internes, et intégration avec le système de navigation du header.
Important
Ce composant NE devrait PAS être utilisé directement, il est utilisé en interne par son parent DsfrNavigationMenu
📐 Structure
Le lien de menu de navigation crée dynamiquement :
- un élément
<a>
pour les liens externes (commençant parhttp
) - un
<RouterLink>
pour les liens internes avec gestion automatique du routeur Vue - une icône optionnelle avec support des icônes DSFR (
fr-icon-*
) ou Iconify - la classe CSS
fr-nav__link
pour le styling DSFR
🛠️ Props
nom | type | défaut | obligatoire | description |
---|---|---|---|---|
id | string | () => useRandomId(...) | Identifiant unique pour le lien | |
to | string | RouteLocationRaw | '#' | Destination du lien (URL ou objet route Vue) | |
text | string | '' | Texte affiché du lien | |
icon | string | VIcon['$props'] | undefined | Icône à afficher (nom Iconify ou props VIcon) | |
onClick | Function | () => undefined | Fonction appelée lors du clic sur le lien |
📡 Événements
DsfrNavigationMenuLink
déclenche l'événement suivant :
nom | donnée (payload) | description |
---|---|---|
toggleId | string | Émis lors du clic pour gérer l'état des menus |
🧩 Slots
DsfrNavigationMenuLink
n'a pas de slots personnalisés.
📝 Exemples
Exemple d'utilisation de DsfrNavigationMenuLink
dans un menu :
vue
<template>
<DsfrNavigationMenu title="Liens utiles">
<DsfrNavigationMenuItem>
<DsfrNavigationMenuLink
to="/accueil"
text="Page d'accueil"
icon="ri-home-line"
/>
</DsfrNavigationMenuItem>
<DsfrNavigationMenuItem>
<DsfrNavigationMenuLink
to="https://www.service-public.fr"
text="Service Public"
icon="fr-icon-external-link-line"
/>
</DsfrNavigationMenuItem>
</DsfrNavigationMenu>
</template>
⚙️ Code source du composant
vue
<script lang="ts" setup>
import type { DsfrNavigationMenuLinkProps } from './DsfrNavigation.types'
import { computed, hasInjectionContext, inject } from 'vue'
import { useRandomId } from '../../utils/random-utils'
import { registerNavigationLinkKey } from '../DsfrHeader/injection-key'
import VIcon from '../VIcon/VIcon.vue'
export type { DsfrNavigationMenuLinkProps }
const props = withDefaults(defineProps<DsfrNavigationMenuLinkProps>(), {
id: () => useRandomId('menu-link'),
icon: undefined,
onClick: () => undefined,
text: '',
to: '#',
})
defineEmits<{ (event: 'toggleId', id: string): void }>()
const isExternal = computed(() => typeof props.to === 'string' && props.to.startsWith('http'))
const dsfrIcon = computed(() => props.icon && typeof props.icon === 'string' && props.icon.startsWith('fr-icon-'))
const defaultScale = 2
const iconProps = computed(() => (dsfrIcon.value || !props.icon)
? undefined
: (typeof props.icon === 'string')
? { scale: defaultScale, name: props.icon }
: { scale: defaultScale, ...((props.icon as Record<string, string>) || {}) },
)
const useHeader = hasInjectionContext() ? inject(registerNavigationLinkKey)! : undefined
const closeModal = useHeader?.() ?? (() => {})
</script>
<template>
<a
v-if="isExternal"
class="fr-nav__link"
data-testid="nav-external-link"
:href="(to as string)"
@click="$emit('toggleId', id); onClick($event)"
>
{{ text }}
</a>
<RouterLink
v-else
class="fr-nav__link"
data-testid="nav-router-link"
:to="to"
:class="{
[String(icon)]: dsfrIcon,
}"
@click="closeModal(); $emit('toggleId', id); onClick?.($event)"
>
<VIcon
v-if="icon && iconProps"
v-bind="iconProps"
/>
{{ text }}
</RouterLink>
</template>
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
)[]
}