<template>
  <transition
      name="expand"
      :duration="500"
      @enter="enter"
      @after-enter="afterEnter"
      @leave="leave">
    <slot></slot>
  </transition>
</template>

<script>

  export default {
    methods: {
      enter(element, done) {
        const width = getComputedStyle(element).width;

        element.style.width = width;
        element.style.position = 'absolute';
        element.style.visibility = 'hidden';
        element.style.height = 'auto';

        const height = getComputedStyle(element).height;

        element.style.width = null;
        element.style.position = null;
        element.style.visibility = null;
        element.style.height = 0;

        // Trigger the animation.
        // We use `setTimeout` because we need
        // to make sure the browser has finished
        // painting after setting the `height`
        // to `0` in the line above.
        setTimeout(() => {
          element.style.height = height;
        });
      },

      afterEnter(element) {
        element.style.height = 'auto';
      },

      leave(element, done) {
        const height = getComputedStyle(element).height;

        element.style.height = height;

        setTimeout(() => {
          element.style.height = 0;
        });
      }
    }
  }

</script>

<style scoped>
  * {
    will-change: height;
    transform: translateZ(0);
    backface-visibility: hidden;
    perspective: 1000px;
  }
</style>