Skip to content

Alertes - DsfrAlert

🌟 Introduction

Les alertes permettent d’attirer l’attention de l’utilisateur sur une information sans interrompre sa tâche en cours.

L’alerte est disponible en deux tailles :

  • taille médium (MD, par défaut, si la prop small est absente ou à false) et
  • petite taille ‘SM’ si la prop small est à true.

🏅 La documentation sur l’alerte sur le DSFR

La story sur l’alerte sur le storybook de VueDsfr

📐 Structure

L’alerte est composée des éléments suivants :

  • un titre (prop title, de type string) :
    • obligatoire sur la version MD (si la prop small est absente ou à false),
    • optionnel sur la version SM (si la prop small est à true).
  • un pictogramme et une couleur déterminés par la prop type qui peut valoir une des chaînes suivantes :
    • 'info' (valeur par défaut si la prop type est absente)
    • 'success'
    • 'warning'
    • 'error'
  • un texte de description (avec la prop description, de type string) :
    • optionnel sur la version MD
    • obligatoire sur la version SM
    • le slot par défaut peut être utilisé
  • une croix de fermeture si la prop closeable est à true

Autres props :

  • closed sert à indiquer si l’alerte doit être présente (false) ou non (true) dans le DOM.
  • titleTag permet d’indiquer la balise à utiliser pour le title : il s’agit de h3 par défaut, cependant, pour passer les tests RGAA, il faut que les niveaux de titres se suivent et soient cohérents (par exemple, si sur la page il n’y a pas de <h2>, il faut passer 'h2' comme valeur à la prop titleTag pour que le titre de la modal soit un <h2>).
  • closeButtonLabel permet d'indiquer le libellé et l'aria-label du bouton de fermeture de l’alerte. Par défaut, la valeur est Fermer.

🛠️ Props

nomtypedéfautobligatoire
idstringrandom string
type'info' | 'success' | 'warning' | 'error''info'
titlestring''
descriptionstring
titleTagTitleTag'h3'
smallbooleanfalse
closedbooleanfalse
closeablebooleanfalse
closeButtonLabelstringFermer

📡 Évenements

DsfrAlert déclenche l’événement 'close' lors du clic sur le bouton pour fermer l’alerte, sans données (sans payload).

nomdonnée (payload)
'close'aucune

🧩 Slots

DsfrAlert possède un slot par défaut pour la description de l'alerte.

📝 Toutes les variantes 🌈 d’Alertes

vue
<script lang="ts" setup>
import { ref } from 'vue'

import type { TitleTag } from '@/common-types'
import DsfrAlert, { type DsfrAlertType } from '../DsfrAlert.vue'

const defaultAlerts: {
  [key: string]: {
    id: string
    type: DsfrAlertType
    title?: string
    small?: true
    description: string
    titleTag: TitleTag
    closed?: boolean
    closeable?: true
  }[]
} = {
  'Grandes non fermables': [
    {
      id: '1',
      type: 'error',
      title: 'Titre de l’erreur',
      description: 'Description de l’erreur',
      titleTag: 'h2',
    },
    {
      id: '2',
      type: 'info',
      title: 'Titre de l’info',
      description: 'Description de l’info',
      titleTag: 'h3',
    },
    {
      id: '3',
      type: 'warning',
      title: 'Titre de l’avertissement',
      description: 'Description de l’avertissement',
      titleTag: 'h4',
    },
    {
      id: '4',
      type: 'success',
      title: 'Titre du succès',
      description: 'Description du succès',
      titleTag: 'h5',
    },
  ],
  'Grandes fermables': [
    {
      id: '5',
      type: 'error',
      title: 'Titre de l’erreur',
      description: 'Description de l’erreur',
      titleTag: 'h2',
      closeable: true,
      closed: false,
    },
    {
      id: '6',
      type: 'info',
      title: 'Titre de l’info',
      description: 'Description de l’info',
      titleTag: 'h3',
      closeable: true,
      closed: false,
    },
    {
      id: '7',
      type: 'warning',
      title: 'Titre de l’avertissement',
      description: 'Description de l’avertissement',
      titleTag: 'h4',
      closeable: true,
      closed: false,
    },
    {
      id: '8',
      type: 'success',
      title: 'Titre du succès',
      description: 'Description du succès',
      titleTag: 'h5',
      closeable: true,
      closed: false,
    },
  ],
  'Petites non fermables': [
    {
      id: '9',
      type: 'error',
      small: true,
      description: 'Description de l’erreur',
      titleTag: 'h2',
    },
    {
      id: '10',
      type: 'info',
      small: true,
      description: 'Description de l’info',
      titleTag: 'h3',
    },
    {
      id: '11',
      type: 'warning',
      small: true,
      description: 'Description de l’avertissement',
      titleTag: 'h4',
    },
    {
      id: '12',
      type: 'success',
      small: true,
      description: 'Description du succès',
      titleTag: 'h5',
    },
  ],
  'Petites fermables': [
    {
      id: '13',
      type: 'error',
      small: true,
      description: 'Description de l’erreur',
      titleTag: 'h2',
      closeable: true,
      closed: false,
    },
    {
      id: '14',
      type: 'info',
      small: true,
      description: 'Description de l’info',
      titleTag: 'h3',
      closeable: true,
      closed: false,
    },
    {
      id: '15',
      type: 'warning',
      small: true,
      description: 'Description de l’avertissement',
      titleTag: 'h4',
      closeable: true,
      closed: false,
    },
    {
      id: '16',
      type: 'success',
      small: true,
      description: 'Description du succès',
      titleTag: 'h5',
      closeable: true,
      closed: false,
    },
  ],
}

const alertGroups = ref(defaultAlerts)

const onClose = (id: string) => {
  Object.values(alertGroups.value)
    .flat()
    .forEach((alert) => {
      if (alert.id === id) {
        alert.closed = true // mettre la propriété closed à true pour cette alerte
        setTimeout(() => { alert.closed = false }, 3000) // la remettre à false au bout de 3 secondes
      }
    })
}
</script>

<template>
  <div class="fr-container fr-p-2w">
    <div
      v-for="(alerts, title, i) in alertGroups"
      :key="`alert-group-${i}`"
      :class="i > 0 ? 'fr-mt-6w' : ''"
    >
      <h2>{{ title }}</h2>
      <DsfrAlert
        v-for="alert in alerts"
        :key="`alert-${alert.id}`"
        :type="alert.type"
        :title="alert.title"
        :description="alert.description"
        :title-tag="alert.titleTag"
        :small="alert.small"
        :closed="alert.closed"
        :closeable="alert.closeable"
        @close="onClose(alert.id)"
      />
    </div>
  </div>
</template>

⚙️ Code source du composant

vue
<script setup lang="ts">
import { getRandomId } from '@/utils/random-utils'

import { computed } from 'vue'
import type { DsfrAlertProps } from './DsfrAlert.types'

export type { DsfrAlertProps, DsfrAlertType } from './DsfrAlert.types'

const props = withDefaults(defineProps<DsfrAlertProps>(), {
  id: () => getRandomId('basic', 'alert'),
  title: '',
  titleTag: 'h3',
  type: 'info',
  closeButtonLabel: 'Fermer',
})

const emit = defineEmits<{ (e: 'close'): void }>()
const onClick = () => emit('close')

const classes = computed(
  () => ([
    `fr-alert--${props.type}`,
    {
      'fr-alert--sm': props.small,
    },
  ]),
)
</script>

<template>
  <div
    v-if="!closed"
    :id="id"
    class="fr-alert"
    :class="classes"
    :role="alert ? 'alert' : undefined"
  >
    <component
      :is="titleTag"
      v-if="!small"
      class="fr-alert__title"
    >
      {{ title }}
    </component>
    <slot>
      {{ description }}
    </slot>
    <button
      v-if="closeable"
      class="fr-btn fr-btn--close"
      :title="closeButtonLabel"
      :aria-label="closeButtonLabel"
      @click="onClick"
    />
  </div>
</template>
ts
import type { TitleTag } from '@/common-types'

export type DsfrAlertType = 'error' | 'success' | 'warning' | 'info'

export type DsfrAlertProps = {
  alert?: boolean
  closed?: boolean
  closeable?: boolean
  id?: string
  title?: string
  description?: string
  small?: boolean
  titleTag?: TitleTag
  type?: DsfrAlertType
  closeButtonLabel?: string
}