Lien de pied de page - DsfrFooterLink
🌟 Introduction
Le composant DsfrFooterLink
de Vue.js permet de créer des liens personnalisés dans le pied de page. Ce composant versatile gère différents types de liens (boutons, liens internes, externes, e-mail) et peut être enrichi d'icônes.
🏅 La documentation sur le pied de page sur le DSFR
La story sur le pied de page sur le storybook de VueDsfr🐨 Structure
Le composant se compose d'une balise <script>
avec TypeScript pour la logique et d'une balise <template>
pour le rendu. La logique détermine le type de lien et la gestion des icônes. Le rendu HTML est dynamique en fonction des propriétés et des conditions d'affichage des icônes.
🛠️ Props
nom | type | défaut | obligatoire |
---|---|---|---|
icon | string | InstanceType\<typeof VIcon>['$props'] | undefined | |
iconAttrs | InstanceType<typeof VIcon>['$props'] & import('vue').HTMLAttributes | {} | |
onClick | ($event: MouseEvent) => void | undefined | |
target | string | '_self' | |
label | string | '' | |
href | string | undefined | |
to | import('vue-router').RouteLocationRaw | undefined | |
path | string | undefined |
📡 Événements
Nom | Description |
---|---|
click | Événement émis lors du clic sur le lien. |
📝 Exemples
Ce composant est utilisé en interne dans DsfrFooter, il n’y a pas de raison de l’utiliser en dehors.
⚙️ Code source du composant
vue
<script lang="ts" setup>
import { computed } from 'vue'
import VIcon from '../VIcon/VIcon.vue'
import type { DsfrFooterLinkProps } from './DsfrFooter.types'
export type { DsfrFooterLinkProps }
const props = withDefaults(defineProps<DsfrFooterLinkProps>(), {
icon: undefined,
iconAttrs: () => ({}),
onClick: () => undefined,
target: undefined,
label: '',
href: undefined,
to: undefined,
})
const isExternalLink = computed(() => {
return props.href?.startsWith('http')
})
const isMailto = computed(() => {
return props.href?.startsWith('mailto')
})
const is = computed(() => {
if (props.button) {
return 'button'
}
return isExternalLink.value || isMailto.value ? 'a' : 'RouterLink'
})
const actualHref = computed(() => {
if (!isExternalLink.value && !isMailto.value) {
return undefined
}
return props.href
})
const actualTo = computed(() => {
if (isExternalLink.value || isMailto.value) {
return undefined
}
return props.to
})
const linkData = computed(() => {
return actualTo.value ? { to: actualTo.value } : { href: actualHref.value }
})
const dsfrIcon = computed(() => typeof props.icon === 'string' && props.icon.startsWith('fr-icon-'))
const defaultScale = 1
const iconProps = computed(() => typeof props.icon === 'string'
? { name: props.icon, scale: defaultScale, ...(props.iconAttrs ?? {}) }
: { scale: defaultScale, ...(props.icon ?? {}), ...(props.iconAttrs ?? {}) },
)
</script>
<template>
<component
:is="is"
class="fr-footer__bottom-link"
:class="{
'fr-btn--icon-right': dsfrIcon && iconRight,
'fr-btn--icon-left': dsfrIcon && !iconRight,
[String(icon)]: dsfrIcon,
}"
v-bind="linkData"
:target="target"
@click.stop="onClick"
>
<template
v-if="!dsfrIcon && (icon || iconAttrs?.name) && !iconRight"
>
<VIcon
class="fr-mr-1w"
v-bind="iconProps"
/>
</template>
{{ label }}
<template
v-if="!dsfrIcon && (icon || iconAttrs?.name) && iconRight"
>
<VIcon
class="fr-ml-1w"
v-bind="iconProps"
/>
</template>
</component>
</template>
ts
import type { HTMLAttributes, StyleValue } from 'vue'
import type { RouteLocationRaw } from 'vue-router'
import type VIcon from '../VIcon/VIcon.vue'
export type DsfrFooterPartner = {
href: string
logo: string
name: string
}
export type DsfrFooterPartnersProps = {
mainPartner?: DsfrFooterPartner
subPartners?: DsfrFooterPartner[]
title?: string
}
export type DsfrFooterLinkProps = {
button?: boolean
icon?: string | InstanceType<typeof VIcon>['$props']
iconAttrs?: InstanceType<typeof VIcon>['$props'] & HTMLAttributes
iconRight?: boolean
label?: string
target?: string
onClick?: ($event: MouseEvent) => void
to?: RouteLocationRaw
href?: string
title?: string
}
export type DsfrFooterLinkListProps = {
categoryName: string
links: DsfrFooterLinkProps[]
}
export type DsfrFooterProps = {
a11yCompliance?: string
a11yComplianceLink?: RouteLocationRaw
legalLink?: string
homeLink?: RouteLocationRaw
homeTitle?: string
partners?: DsfrFooterPartnersProps
personalDataLink?: string
cookiesLink?: string
logoText?: string | string[]
descText?: string
beforeMandatoryLinks?: DsfrFooterLinkProps[]
afterMandatoryLinks?: DsfrFooterLinkProps[]
mandatoryLinks?: { label: string, to: RouteLocationRaw | undefined, title?: string }[]
ecosystemLinks?: { label: string, href: string, title: string, [key: string]: string }[]
operatorLinkText?: string
operatorTo?: RouteLocationRaw | undefined
operatorImgStyle?: StyleValue
operatorImgSrc?: string
operatorImgAlt?: string
licenceTo?: string
licenceLinkProps?: ({ href: string } | { to: RouteLocationRaw | undefined }) & Record<string, string>
licenceText?: string
licenceName?: string
}