Search code examples
vue.jsvuejs3vue-transitions

Why is my transition not working on "leave"?


I have a global confirmModal.vue which looks like this:

<template>
  <Transition
    appear
    enter-from-class="opacity-0"
    enter-to-class="opacity-100"
    leave-from-class="opacity-100"
    leave-to-class="opacity-0"
  >
    <div
      @click="$emit('cancel')"
      class="bg-black/50 z-50 fixed inset-0 flex justify-center items-center transition duration-300 ease-in-out p-8 cursor-pointer"
    >
      <Transition appear enter-from-class="scale-50" enter-to-class="scale-100">
        <div
          @click.stop
          class="flex flex-col gap-4 shadow-2xl p-8 rounded min-w-[300px] max-w-[480px] bg-lf-white transition duration-300 ease-in-out cursor-auto"
        >
          <h3 class="font-medium text-2xl">{{ title }}</h3>
          <p>{{ text }}</p>

          <div class="flex justify-end gap-2">
            <Button @click="$emit('cancel')" variant="white">Annuler</Button>
            <Button @click="$emit('confirm')">Supprimer</Button>
          </div>
        </div>
      </Transition>
    </div>
  </Transition>
</template>

The first transition adds a fade in effect to the backdrop while the nested transition adds a smooth apparition effect for the modal itself.

It works fine but what I don't understand is that when I close the modal, the leave part of the transition does not trigger at all.

This is what the component calling this modal looks like:

<ConfirmModal
  v-if="showConfirmModal"
  title="Suppression"
  text="Êtes-vous sûr de vouloir supprimer cet article ?"
  @cancel="handleHideConfirmModal"
  @confirm="handleConfirmAction"
/>

Here's a gif of what it's currently looks like:

enter image description here

EDIT: I achieved the wanted result by wrapping ConfirmModal.vue with Transition from the parent component, like this:

    <Transition
      enter-from-class="opacity-0"
      enter-to-class="opacity-100"
      leave-from-class="opacity-100"
      leave-to-class="opacity-0"
    >
      <ConfirmModal
        v-if="showConfirmModal"
        title="Suppression"
        text="Êtes-vous sûr de vouloir supprimer cet article ?"
        @cancel="handleHideConfirmModal"
      />
    </Transition>

I don't understand why I have to do this and why in this exemple the person doesn't need to do that though, they use Transition from inside the child component and the transition works fine

It's also not ideal because every time I use this component I will have to think to wrap it inside this transition for it to fully work


Solution

  • It's probably caused by the use of different versions of Vue.

    Your question is tagged vuejs3, so you are very likely using Vue 3, but, in the example you linked, vue version 2.6.4 is being used.

    In vue 3, at least, you must use the directives v-if or v-show in the root element inside the Transition component for it to trigger the changes whenever the root component inside appears and disappears.

    you can read more about transitions here