Files
Situation-Awareness-Platfor…/src/components/AIRepair/Panel.vue
2025-03-14 20:03:14 +08:00

104 lines
2.2 KiB
Vue

<template>
<div>
<slot name="header"></slot>
</div>
<Transition
name="collapse-transition"
@beforeEnter="beforeEnter"
@enter="enter"
@afterEnter="afterEnter"
@beforeLeave="beforeLeave"
@leave="leave"
@afterLeave="afterLeave"
>
<div v-if="props.expand">
<slot name="body"></slot>
</div>
</Transition>
</template>
<script setup lang="ts">
import { ref, defineProps, type RendererElement } from 'vue';
const props = defineProps({
expand: {
type: Boolean,
required: true
},
});
const beforeEnter = (el: RendererElement) => {
if (!el.dataset) {
el.dataset = {};
}
if (el.style.height) {
el.dataset.height = el.style.height;
}
el.style.maxHeight = 0;
};
const enter = (el: RendererElement) => {
requestAnimationFrame(() => {
el.dataset.oldOverflow = el.style.overflow;
if (el.dataset.height) {
el.style.maxHeight = el.dataset.height;
} else if (el.scrollHeight !== 0) {
el.style.maxHeight = `${el.scrollHeight}px`;
} else {
el.style.maxHeight = 0;
}
el.style.overflow = 'hidden';
});
};
const afterEnter = (el: RendererElement) => {
el.style.maxHeight = '';
el.style.overflow = el.dataset.oldOverflow;
};
const beforeLeave = (el: RendererElement) => {
if (!el.dataset) {
el.dataset = {};
}
el.dataset.oldOverflow = el.style.overflow;
el.style.maxHeight = `${el.scrollHeight}px`;
el.style.overflow = 'hidden';
};
const leave = (el: RendererElement) => {
if (el.scrollHeight !== 0) {
el.style.maxHeight = 0;
}
};
const afterLeave = (el: RendererElement) => {
el.style.maxHeight = '';
el.style.overflow = el.dataset.oldOverflow;
};
</script>
<style scoped lang="scss">
.v-enter-active,
.v-leave-active {
transition: opacity 0.5s ease;
}
.v-enter-from,
.v-leave-to {
opacity: 0;
}
.collapse-transition {
&-enter-from,
&-leave-to {
opacity: 0;
}
&-enter-to,
&-leave-from {
opacity: 1;
}
&-enter-active,
&-leave-active {
transition:
max-height 0.3s cubic-bezier(0.5, 0.05, 0.5, 0.95),
opacity 0.3s cubic-bezier(0.5, 0.05, 0.5, 0.95);
}
}
</style>