Enter/exit transitions

Pose for Vue includes a spin on the Vue transition component, PoseTransition.

Its used for animating a single component as it’s added or removed from the DOM.

In this tutorial we’ll learn how to use it to animate a single component as it enters and leaves the DOM.

Setup

Begin by forking this CodeSandbox playground.

It’s set up with some basic styles, and a button that sets an isVisible data property to true.

Adding the modal

First lets add a modal that gets conditionally rendered when isVisible is true.

In our template, add after the button:

<div class="shade" v-if="isVisible">
  <div class="modal" />
</div>

Now, when you click the button, the modal is added to the DOM.

To animate this, we can use PoseTransition. At the top of the script section, import it:

import { PoseTransition } from 'vue-pose';

Pass this through to our template by providing it in the components property of our exported component:

export default {
  data: () => ({ isVisible: false }),
  components: { PoseTransition }
};

Now in our template section we can wrap our newly-added HTML with the PoseTransition component:

<PoseTransition>
  <div class="shade" v-if="isVisible">
    <div class="modal" />
  </div>
</PoseTransition>

Awesome! Our modal now fades in when we click the button.

If we add a new event to our shade div, we can see it also fades out when we remove the modal:

<div class="shade" v-if="isVisible" v-on:click="isVisible = false">

Custom transition

In many cases, we’ll want to customise the animation used as components animate in and out.

We can do this by using posed components.

Import posed:

import posed, { PoseTransition } from 'vue-pose';

Now made a new component for Shade. It’s already a div, so let’s use a div. We can define anything we want for the 'enter' and 'exit' poses, but for now lets just animate opacity with a quicker transition:

components: {
  PoseTransition,
  Shade: posed.div({
    enter: {
      opacity: 1,
      transition: { duration: 200 }
    },
    exit: { opacity: 0 }
  })
}

Now replace the direct child of PoseTransition with Shade:

<PoseTransition>
  <Shade class="shade" v-if="isVisible" v-on:click="isVisible = false">
    <div class="modal" />
  </Shade>
</PoseTransition>

And now the modal fades in faster! But wait, it doesn’t fade out any more…

We can fix this by changing v-on:click with v-on:click.native. This tells Vue we want to add the event listener to the underlying element.

Animating children

It’d be cooler if we could do an animation that involves the white modal box, too. Well, we can! As we saw before, poses get propagated throughout the DOM, and components under PoseTransition are no different.

Replace our modal div with:

<Modal class="modal" />

And add a new posed component called Modal to components:

Modal: posed.div({
  enter: { opacity: 1, z: 0 },
  exit: { opacity: 0, z: -150 }
})

Now the modal animates too! But all the animations happen at the same time. We can adjust the timings by providing some extra props to Shade.

By adding beforeChildren to enter and afterChildren to exit, we can ensure that Modal animates separately to Shade:

Shade: posed.div({
  enter: {
    opacity: 1,
    beforeChildren: true,
    transition: { duration: 200, ease: "linear" }
  },
  exit: {
    opacity: 0,
    afterChildren: true,
    transition: { duration: 200, ease: "linear" }
  }
}),

Conclusion

There’s more to PoseTransition, like animating between sibling components, and animating on mount. Find out its full capabilities with the full API docs.