Chaque page de documentation se termine par « Cette page vous a-t-elle été
utile ? », et la couche ne fait rien de la réponse : elle la garde dans l’état
du composant le temps de la visite, émet un événement et ne stocke rien.
Envelopper le composant est la façon dont la réponse vous parvient.

## Étapes

::steps

1. **Enveloppez le composant de la couche sous son propre nom.** Nuxt résout
   votre fichier en premier : `app/components/DuxtPageFeedback.vue` dans votre
   projet remplace donc celui de la couche — et l’alias `@duxt` atteint toujours
   l’original par son chemin, si bien que l’enveloppe conserve le balisage, les
   traductions et la réinitialisation à la navigation de la couche :

   ```vue [app/components/DuxtPageFeedback.vue]
   <script setup lang="ts">
   import DuxtPageFeedbackBase from '@duxt/components/DuxtPageFeedback.vue';

   const route = useRoute();

   // L’événement porte la réponse et rien d’autre — la page à laquelle elle se
   // rapporte, c’est à vous de la lire, et `fullPath` est celle qui conserve les
   // préfixes de locale, de dépôt et de version sous lesquels la réponse a
   // réellement été donnée.
   async function onFeedback(helpful: boolean) {
     await $fetch('/api/feedback', {
       method: 'POST',
       body: { path: route.fullPath, helpful }
     });
   }
   </script>

   <template>
     <DuxtPageFeedbackBase @feedback="onFeedback" />
   </template>
   ```

2. **Donnez à la réponse un endroit où atterrir.** Une route à vous, pour que le
   navigateur du lecteur ne parle jamais à un tiers que vous n’avez pas choisi :

   ```ts [server/api/feedback.post.ts]
   export default defineEventHandler(async (event) => {
     const { path, helpful } = await readBody(event);

     // Votre stockage, votre analytique, votre file d’attente.
     await recordFeedback({ path, helpful });

     return { ok: true };
   });
   ```

   Un appel d’analytique côté client fonctionne pareil — remplacez le `$fetch`
   de l’enveloppe par ce qu’expose le SDK de votre fournisseur.

3. **Recompilez et répondez une fois à la question**, puis vérifiez que la
   réponse est arrivée avec le chemin attendu — sous un préfixe de version, et
   pas seulement à l’URL nue.

::

::callout{type="tip" title="Une seule destination pour tout ?"}
La même réponse est aussi un événement d’analytique `feedback`. Si les
recherches, les copies et les requêtes d’essai doivent atterrir là où
atterrissent les retours, écrivez une seule fonction de rappel plutôt qu’une
enveloppe — voir
[Envoyer des événements d’analytique](/guides/send-analytics-events). Les deux
sont indépendants : l’événement et le slot de ce composant fonctionnent que
`duxt.analytics.track` soit défini ou non.
::

## Afficher votre propre contrôle

L’événement conserve les boutons de la couche. Pour les remplacer, prenez plutôt
le slot par défaut : il expose l’état même à partir duquel le composant s’affiche,
si bien que la réinitialisation à la navigation et l’état « merci » restent
l’affaire de la couche.

```vue [app/components/DuxtPageFeedback.vue]
<script setup lang="ts">
import DuxtPageFeedbackBase from '@duxt/components/DuxtPageFeedback.vue';
</script>

<template>
  <DuxtPageFeedbackBase v-slot="{ answered, answer }">
    <form v-if="answered === undefined" @submit.prevent="answer(true)">
      <label>
        Dites-nous ce qui manque
        <textarea name="comment" />
      </label>
      <button type="submit">Envoyer</button>
    </form>
    <p v-else>Merci.</p>
  </DuxtPageFeedbackBase>
</template>
```

`answer(helpful)` fixe l’état et émet l’événement : un slot et un écouteur se
composent donc — accrochez votre formulaire au slot et gardez le gestionnaire
`@feedback` de l’étape 1 pour livrer ce qu’il a recueilli.

::callout{type="warning" title="Deux réponses ne font pas deux lecteurs"}
Rien dans le composant n’identifie un visiteur, et cela reste ainsi
délibérément. Si vous comptez les réponses par page, comptez-les comme des
réponses — un navigateur qui recharge et répond à nouveau est une deuxième
réponse, pas un deuxième lecteur, et transformer l’une en l’autre est une
question de consentement à laquelle votre politique de confidentialité doit
répondre d’abord.
::

## Pourquoi la couche ne stocke rien

Un thème de documentation qui téléphonerait à la maison par défaut devrait
choisir une destination pour les lecteurs de quelqu’un d’autre, et il n’en
existe aucune défendable : la couche ne sait ni où vit votre analytique ni ce
que promet votre politique de confidentialité. Livrer la question avec un
événement et sans backend garde la décision là où elle appartient — la même
raison pour laquelle la rangée légale du pied de page et les liens vers le dépôt
sont livrés vides
([ADR 0005](/adr/0005-ship-the-layer-without-owner-specific-links)).

## Liste de contrôle

- [ ] L’enveloppe affiche le composant de la couche au lieu de le réimplémenter
- [ ] La réponse est envoyée avec le chemin sur lequel elle a été donnée,
      préfixes compris
- [ ] La destination est la vôtre — une route, une file ou un SDK que vous avez
      choisi
- [ ] Rien dans la charge utile n’identifie le lecteur