Tag - DsfrTag
🌟 Introduction
Le tag catégorise/classe/organise les contenus à l'aide de mots-clés. Il aide les utilisateurs à rechercher et à trouver facilement une information.
Le tag peut être utilisé dans deux contextes :
Dans le contenu (carte, en-tête, liste) : il catégorise le contenu auquel il est apposé. Il peut être cliquable ou non cliquable ;
En tant que filtre (dans une page de résultats de recherche par exemple). Dans ce cas il peut-être :
- activable comme filtre en place à sélectionner/désélectionner ;
- supprimable, il sert de rappel à un filtre qui a été coché dans une sidebar ou une liste déroulante.
🏅 La documentation sur le tag sur le DSFR
La story sur le tag sur le storybook de VueDsfr📐 Structure
Il se compose des éléments suivants :
- un libellé obligatoire : soit en utilisant la prop
label
soit en utilisant le slot par défaut ; - une icône optionnelle : avec la prop
icon
qui peut être soit le nom d’une classe correspondant à une icône du DSFR (elle commence par'fr-icon-'
), soit le nom d’une icône de@iconify/vue
, cf. la documentation sur les icônes) et celle du composant VIcon.
🛠️ Props
Nom | Type | Défaut | Obligatoire | Description |
---|---|---|---|---|
label | String | undefined | Le texte affiché sur l'étiquette. | |
link | String | undefined | URL pour un lien externe. Détermine aussi le type de balise (a ou RouterLink). | |
tagName | String | 'p' | Nom de la balise utilisée pour l'étiquette. | |
icon | String | undefined | Nom de l'icône (@iconify/vue ) à afficher sur l'étiquette. | |
disabled | Boolean | false | Désactive l'étiquette si elle est un bouton. | |
small | Boolean | false | Réduit la taille de l'étiquette. | |
iconOnly | Boolean | false | Affiche uniquement l'icône, sans texte. |
📡 Évenements
Pas d'événements personnalisés pour ce composant. Il se repose sur les événements natifs de ses balises sous-jacentes.
🧩 Slots
Nom | Description |
---|---|
default | Slot par défaut pour ajouter du contenu supplémentaire à côté du label ou de l'icône. |
📝 Exemples
vue
<script lang="ts" setup>
import DsfrTag from '@/components/DsfrTag/DsfrTag.vue'
</script>
<template>
<div class="flex gap-2 fr-m-2v flex-wrap">
<DsfrTag
label="Vue Power"
/>
<DsfrTag
label="DSFR"
icon="fr-icon-success-line"
/>
<DsfrTag
label="Iconify Power"
icon="ri-bell-line"
/>
<DsfrTag
label="Tag inactif (disabled)"
icon="ri-stop-line"
title="désactivé"
disabled
/>
<DsfrTag
label="Icône seule"
title="Icône seule"
icon="ri-play-line"
icon-only
/>
<DsfrTag
label="Petit tag"
title="Petite"
small
/>
<DsfrTag
label="Petit tag avec icone DSFR"
title="Petite"
small
icon="fr-icon-success-line"
/>
<DsfrTag
label="Petit tag avec icone Iconify"
title="Petite"
small
icon="ri-checkbox-circle-line"
/>
</div>
</template>
⚙️ Code source du composant
vue
<script lang="ts" setup>
import { computed } from 'vue'
import VIcon from '../VIcon/VIcon.vue'
import type { DsfrTagProps } from './DsfrTags.types'
export type { DsfrTagProps }
const props = withDefaults(defineProps<DsfrTagProps>(), {
label: undefined,
link: undefined,
tagName: 'p',
icon: undefined,
})
const isExternalLink = computed(() => typeof props.link === 'string' && props.link.startsWith('http'))
const is = computed(() => {
return props.link
? (isExternalLink.value ? 'a' : 'RouterLink')
: ((props.disabled && props.tagName === 'p') ? 'button' : props.tagName)
})
const linkProps = computed(() => {
return { [isExternalLink.value ? 'href' : 'to']: props.link }
})
const dsfrIcon = computed(() => typeof props.icon === 'string' && props.icon.startsWith('fr-icon-'))
const defaultScale = props.small ? 0.65 : 0.9
const iconProps = computed(() => dsfrIcon.value ? undefined : typeof props.icon === 'string' ? { name: props.icon, scale: defaultScale } : { scale: defaultScale, ...(props.icon ?? {}) })
</script>
<template>
<component
:is="is"
class="fr-tag"
:disabled="disabled"
:class="{
'fr-tag--sm': small,
[icon as string]: dsfrIcon,
'fr-tag--icon-left': dsfrIcon,
}"
v-bind="linkProps"
>
<VIcon
v-if="props.icon && !dsfrIcon"
:label="iconOnly ? label : undefined"
class="fr-mr-1v"
v-bind="iconProps"
/>
<template v-if="!iconOnly">
{{ label }}
</template>
<!-- @slot Slot par défaut pour le contenu du tag -->
<slot />
</component>
</template>
<style scoped>
.ov-icon {
margin-top: 0.1rem;
}
.fr-tag {
align-items: center;
}
.success {
color: var(--success);
background-color: var(--bg-success);
}
.error {
color: var(--error);
background-color: var(--bg-error);
}
.warning {
color: var(--warning);
background-color: var(--bg-warning);
}
.info {
color: var(--info);
background-color: var(--bg-info);
}
</style>
ts
export type DsfrTagProps = {
label?: string
link?: string
tagName?: string
icon?: string
disabled?: boolean
small?: boolean
iconOnly?: boolean
}
export type DsfrTagsProps = {
tags: DsfrTagProps[]
}