targo-frontend/src/modules/shared/components/horizontal-slide-transition.vue
2025-12-09 16:59:53 -05:00

79 lines
1.9 KiB
Vue

<script
setup
lang="ts"
>
defineProps({
show: { type: Boolean, required: true }
})
const beforeEnter = (element: Element) => {
const html_element = element as HTMLElement;
html_element.style.width = '0'
html_element.style.opacity = '0'
}
const enter = (element: Element) => {
const html_element = element as HTMLElement;
const w = html_element.scrollWidth
html_element.style.transition = 'width 0.25s ease, opacity 0.25s ease'
requestAnimationFrame(() => {
html_element.style.width = w + 'px'
html_element.style.opacity = '1'
})
}
const afterEnter = (element: Element) => {
const html_element = element as HTMLElement;
html_element.style.width = 'auto' // restore natural width
}
const beforeLeave = (element: Element) => {
const html_element = element as HTMLElement;
html_element.style.width = element.scrollWidth + 'px'
html_element.style.opacity = '1'
}
const leave = (element: Element) => {
const html_element = element as HTMLElement;
// force reflow
void html_element.offsetWidth
html_element.style.transition = 'width 0.25s ease, opacity 0.25s ease'
html_element.style.width = '0'
html_element.style.opacity = '0'
}
</script>
<template>
<transition
@before-enter="beforeEnter"
@enter="enter"
@after-enter="afterEnter"
@before-leave="beforeLeave"
@leave="leave"
>
<div
v-show="show"
class="h-slide"
>
<slot />
</div>
</transition>
</template>
<style scoped>
.h-slide {
overflow: hidden;
/* required for width transitions */
display: inline-block;
/* ensures width applies correctly */
}
</style>