69 lines
1.3 KiB
Vue
69 lines
1.3 KiB
Vue
<script setup lang="ts">
|
|
defineProps<{
|
|
show: boolean
|
|
}>()
|
|
|
|
const emit = defineEmits<{
|
|
close: []
|
|
}>()
|
|
</script>
|
|
|
|
<template>
|
|
<Teleport to="body">
|
|
<Transition name="modal">
|
|
<div v-if="show" class="modal-overlay" @click.self="emit('close')">
|
|
<div class="modal-panel">
|
|
<slot />
|
|
</div>
|
|
</div>
|
|
</Transition>
|
|
</Teleport>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.modal-overlay {
|
|
position: fixed;
|
|
inset: 0;
|
|
z-index: 1000;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: rgba(26, 26, 46, 0.3);
|
|
backdrop-filter: blur(6px);
|
|
}
|
|
|
|
.modal-panel {
|
|
background: var(--paper-50);
|
|
border: 1px solid var(--paper-200);
|
|
border-radius: var(--radius-lg);
|
|
padding: var(--space-xl);
|
|
max-width: 560px;
|
|
width: 90%;
|
|
max-height: 85vh;
|
|
overflow-y: auto;
|
|
box-shadow: var(--shadow-lg);
|
|
}
|
|
|
|
/* 转场动画 */
|
|
.modal-enter-active {
|
|
transition: opacity var(--duration-normal) ease;
|
|
}
|
|
|
|
.modal-leave-active {
|
|
transition: opacity var(--duration-fast) ease;
|
|
}
|
|
|
|
.modal-enter-from,
|
|
.modal-leave-to {
|
|
opacity: 0;
|
|
}
|
|
|
|
.modal-enter-active .modal-panel {
|
|
animation: scaleIn var(--duration-normal) var(--ease-out-back) both;
|
|
}
|
|
|
|
.modal-leave-active .modal-panel {
|
|
animation: scaleIn var(--duration-fast) ease reverse both;
|
|
}
|
|
</style>
|