Accordéon - DsfrAccordion 
🌟 Introduction 
Les accordéons permettent aux utilisateurs d'afficher et de masquer des sections de contenu présentés dans une page.
🏅 La documentation sur l’accordéon sur le DSFR
La story sur l’accordéon sur le storybook de VueDsfr📐 Structure 
Un accordéon est constitué des éléments suivants :
- un en-tête (prop title, de typestring), correspondant au titre de la section - obligatoire.
- une icône, indique quand le panneau est fermé, quand le panneau est ouvert.
- un séparateur
- une zone de contenu, masquée par défaut pouvant contenir tout type d'élément, le slotpar défaut est fait pour ça
Autres props :
- id: identifiant du contenu de l’accordéon, qui est utilisé aussi pour l’attribut- aria-controlsdu bouton qui permet de plier et déplier l’accordéon
- expandedId: identifiant de l’accordéon actuellement déplié (pour savoir si l’accordéon doit être déplié)
🛠️ Props 
| Nom | Type | Défaut | Obligatoire | 
|---|---|---|---|
| title | string | useRandomId('accordion') | ✅ | 
| titleTag | TitleTag | 'h3' | |
| id | string | random string | 
📡Évenements 
Pas d'événements spécifiques émis directement par ce composant.
🧩 Slots 
- title: Slot pour le contenu personnalisé du titre de l’accordéon. Si non utilisé, le texte fourni via la prop- titlesera utilisé.
- default: Slot pour le contenu principal de l'accordéon, affiché dans la section repliable.
📝 Exemples 
Ce composant peut être utilisé uniquement avec DsfrAccordionsGroup.
⚙️Code source du composant 
vue
<script lang="ts" setup>
import type { DsfrAccordionProps } from './DsfrAccordion.types'
import { inject, onMounted, ref, toRef, watch } from 'vue'
import { useCollapsable } from '../../composables'
import { useRandomId } from '../../utils/random-utils'
import { registerAccordionKey } from './injection-key'
export type { DsfrAccordionProps }
const props = withDefaults(
  defineProps<DsfrAccordionProps>(),
  {
    id: () => useRandomId('accordion'),
    title: 'Sans intitulé',
    titleTag: 'h3',
  },
)
const {
  collapse,
  collapsing,
  cssExpanded,
  doExpand,
  onTransitionEnd,
} = useCollapsable()
const isStandaloneActive = ref()
const useAccordion = inject(registerAccordionKey)!
const { isActive, expand } = useAccordion?.(toRef(() => props.title)) ?? { isActive: isStandaloneActive, expand: () => isStandaloneActive.value = !isStandaloneActive.value }
onMounted(() => {
  // Accordion can be expanded by default
  // We need to trigger the expand animation on mounted
  if (isActive.value) {
    doExpand(true)
  }
})
watch(isActive, (newValue, oldValue) => {
  /*
  * @see https://github.com/GouvernementFR/dsfr/blob/main/src/dsfr/core/script/collapse/collapse.js
  */
  if (newValue !== oldValue) {
    doExpand(newValue)
  }
})
</script>
<template>
  <section class="fr-accordion">
    <component
      :is="titleTag"
      class="fr-accordion__title"
    >
      <button
        class="fr-accordion__btn"
        :aria-expanded="isActive"
        :aria-controls="id"
        type="button"
        @click="expand()"
      >
        <!-- @slot Slot pour le contenu personnalisé du titre de l’accordéon. Une **props du même nom est utilisable pour du texte simple** sans mise en forme. -->
        <slot name="title">
          {{ title }}
        </slot>
      </button>
    </component>
    <div
      :id="id"
      ref="collapse"
      class="fr-collapse"
      :class="{
        'fr-collapse--expanded': cssExpanded, // Need to use a separate data to add/remove the class after a RAF
        'fr-collapsing': collapsing,
      }"
      @transitionend="onTransitionEnd(isActive, false)"
    >
      <!-- @slot Slot par défaut pour le contenu de l’accordéon: sera dans `<div class="fr-collapse">` -->
      <slot />
    </div>
  </section>
</template>ts
import type { TitleTag } from '../../common-types'
export type DsfrAccordionProps = {
  id?: string
  selected?: boolean
  title?: string
  titleTag?: TitleTag
}ts
import type { InjectionKey, Ref } from 'vue'
type RegisterTab = (title: Ref<string>) => {
  isActive: Ref<boolean>
  expand: () => void
}
export const registerAccordionKey: InjectionKey<RegisterTab> = Symbol('accordions')