74 lines
1.5 KiB
Vue
74 lines
1.5 KiB
Vue
<script setup>
|
|
console.log('Transition started')
|
|
function enter(el, done) {
|
|
const width = getComputedStyle(el).width
|
|
console.log('@enter')
|
|
el.style.width = width
|
|
el.style.position = 'absolute'
|
|
el.style.visibility = 'hidden'
|
|
el.style.height = 'auto'
|
|
|
|
const height = getComputedStyle(el).height
|
|
|
|
el.style.width = ''
|
|
el.style.position = ''
|
|
el.style.visibility = ''
|
|
el.style.height = '0'
|
|
|
|
// Force repaint to make sure the
|
|
// animation is triggered correctly.
|
|
getComputedStyle(el).height
|
|
|
|
// Trigger the animation.
|
|
// We use `requestAnimationFrame` because we need
|
|
// to make sure the browser has finished
|
|
// painting after setting the `height`
|
|
// to `0` in the line above.
|
|
requestAnimationFrame(() => {
|
|
el.style.height = height
|
|
})
|
|
|
|
done()
|
|
}
|
|
|
|
function afterEnter(element) {
|
|
console.log('@after-enter')
|
|
element.style.height = 'auto'
|
|
}
|
|
|
|
function leave(element) {
|
|
console.log('@leave')
|
|
const height = getComputedStyle(element).height
|
|
|
|
element.style.height = height
|
|
|
|
// Force repaint to make sure the
|
|
// animation is triggered correctly.
|
|
getComputedStyle(element).height
|
|
|
|
requestAnimationFrame(() => {
|
|
element.style.height = '0'
|
|
})
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<Transition
|
|
name="expand"
|
|
@enter="enter"
|
|
@after-enter="afterEnter"
|
|
@leave="leave"
|
|
>
|
|
<slot />
|
|
</Transition>
|
|
</template>
|
|
|
|
<style scoped lang="scss">
|
|
* {
|
|
will-change: height;
|
|
transform: translateZ(0);
|
|
backface-visibility: hidden;
|
|
perspective: 1000px;
|
|
}
|
|
</style>
|