96 lines
1.9 KiB
Vue
96 lines
1.9 KiB
Vue
<template>
|
|
<Teleport to="body">
|
|
<Transition name="modal">
|
|
<div
|
|
v-if="active"
|
|
class="fixed inset-0 bg-black/70 flex items-center justify-center z-50 p-4"
|
|
@click="handleOverlayClick"
|
|
>
|
|
<div
|
|
class="bg-white rounded-lg shadow-2xl max-h-[90vh] overflow-y-auto relative"
|
|
:class="sizeClass"
|
|
@click.stop
|
|
>
|
|
<slot></slot>
|
|
</div>
|
|
</div>
|
|
</Transition>
|
|
</Teleport>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { computed, watch, onBeforeUnmount } from 'vue'
|
|
|
|
const props = defineProps({
|
|
active: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
size: {
|
|
type: String,
|
|
default: 'md',
|
|
validator: (value) => ['xs', 'sm', 'md', 'lg', 'xl', '2xl', '3xl', '4xl', 'full'].includes(value)
|
|
},
|
|
clickOutside: {
|
|
type: [Boolean, String],
|
|
default: true
|
|
}
|
|
})
|
|
|
|
const emit = defineEmits(['close'])
|
|
|
|
const sizeClass = computed(() => {
|
|
const sizes = {
|
|
xs: 'w-full max-w-xs',
|
|
sm: 'w-full max-w-sm',
|
|
md: 'w-full max-w-md',
|
|
lg: 'w-full max-w-lg',
|
|
xl: 'w-full max-w-xl',
|
|
'2xl': 'w-full max-w-2xl',
|
|
'3xl': 'w-full max-w-3xl',
|
|
'4xl': 'w-full max-w-4xl',
|
|
full: 'w-[95vw] h-[95vh] max-w-none max-h-none'
|
|
}
|
|
return sizes[props.size] || sizes.md
|
|
})
|
|
|
|
const handleOverlayClick = () => {
|
|
if (clickOutside.value) {
|
|
emit('close')
|
|
}
|
|
}
|
|
|
|
watch(() => props.active, (newVal) => {
|
|
if (newVal) {
|
|
document.body.style.overflow = 'hidden'
|
|
} else {
|
|
document.body.style.overflow = ''
|
|
}
|
|
})
|
|
|
|
onBeforeUnmount(() => {
|
|
document.body.style.overflow = ''
|
|
})
|
|
</script>
|
|
|
|
<style>
|
|
.modal-enter-active,
|
|
.modal-leave-active {
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.modal-enter-from,
|
|
.modal-leave-to {
|
|
opacity: 0;
|
|
}
|
|
|
|
.modal-enter-from .bg-white,
|
|
.modal-leave-to .bg-white {
|
|
transform: scale(0.95) translateY(-20px);
|
|
}
|
|
|
|
.modal-enter-active .bg-white,
|
|
.modal-leave-active .bg-white {
|
|
transition: transform 0.3s ease;
|
|
}
|
|
</style> |