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 labelsoit en utilisant le slot par défaut ;
- une icône optionnelle : avec la prop iconqui 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 (devrait être 'p'ou'button'). | |
| icon | string | InstanceType<typeof VIcon>['$props'] | undefined | Icône à afficher dans le tag Peut être un nom ou une configuration d'icône. | |
| disabled | boolean | undefined | Désactive l'étiquette si elle est un bouton. | |
| small | boolean | undefined | Réduit la taille de l'étiquette. | |
| iconOnly | boolean | undefined | Affiche uniquement l'icône, sans texte. | |
| selectable | boolean | false | Rend le tag sélectionnable. | |
| selected | boolean(si selectable) | false | Indique si le tag est sélectionné. | |
| value | T(si selectable) | undefined | Valeur associée au tag (utile dans une liste de tags sélectionnables). | 
📡 É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 { ref } from 'vue'
import DsfrTag from '@/components/DsfrTag/DsfrTag.vue'
const loneTag = ref(false)
const filters = ref(['individualTags', 'tagSets'])
</script>
<template>
  <div
    v-if="filters.includes('individualTags')"
    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"
    />
    <DsfrTag
      label="Tag tout cliquable seul !"
      selectable
      :selected="loneTag"
      @select="loneTag = !loneTag"
    />
    <DsfrTag
      label="Tag cliquable tout seul mais désactivé !"
      selectable
      disabled
      :selected="loneTag"
      @select="loneTag = !loneTag"
    />
  </div>
</template>⚙️ Code source du composant 
vue
<script lang="ts" setup generic="T = string">
import type { DsfrTagProps } from './DsfrTags.types'
import { computed } from 'vue'
import VIcon from '../VIcon/VIcon.vue'
const props = withDefaults(defineProps<DsfrTagProps<T>>(), {
  label: undefined,
  link: undefined,
  tagName: 'p',
  icon: undefined,
  disabled: undefined,
})
defineEmits<{
  select: [[unknown, boolean]]
}>()
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') || props.selectable) ? '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 = computed(() => props.small ? 0.65 : 0.9)
const iconProps = computed(() => typeof props.icon === 'string'
  ? { scale: defaultScale.value, name: props.icon }
  : { scale: defaultScale.value, ...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,
    }"
    :aria-pressed="selectable ? selected : undefined"
    v-bind="{ ...linkProps, ...$attrs }"
    @click="!disabled && $emit('select', [value, selected])"
  >
    <VIcon
      v-if="props.icon && !dsfrIcon"
      :label="iconOnly ? label : undefined"
      :class="{ 'fr-mr-1v': !iconOnly }"
      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
import type VIcon from '../VIcon/VIcon.vue'
export type DsfrTagProps<T = string> = {
  label?: string
  link?: string
  tagName?: string
  icon?: string | InstanceType<typeof VIcon>['$props']
  disabled?: boolean
  small?: boolean
  iconOnly?: boolean
} & ({
  selectable: true
  selected?: boolean
  value?: T
} | {
  selectable?: false
})
export type DsfrTagsProps<T = string> = {
  tags: DsfrTagProps<T>[]
  modelValue?: T[]
}