46 lines
986 B
Vue
46 lines
986 B
Vue
|
|
<template>
|
||
|
|
<Teleport to="body">
|
||
|
|
<div
|
||
|
|
v-if="message"
|
||
|
|
:class="[
|
||
|
|
'fixed top-4 right-4 p-4 rounded-lg shadow-lg z-50 transform transition-all duration-300',
|
||
|
|
type === 'success' ? 'bg-green-500' : 'bg-red-500',
|
||
|
|
'text-white'
|
||
|
|
]"
|
||
|
|
:style="{ transform: show ? 'translateY(0)' : 'translateY(-100%)' }"
|
||
|
|
>
|
||
|
|
{{ message }}
|
||
|
|
</div>
|
||
|
|
</Teleport>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script setup lang="ts">
|
||
|
|
import { ref, watch } from 'vue';
|
||
|
|
|
||
|
|
interface Props {
|
||
|
|
message?: string;
|
||
|
|
type?: 'success' | 'error';
|
||
|
|
duration?: number;
|
||
|
|
}
|
||
|
|
|
||
|
|
const props = withDefaults(defineProps<Props>(), {
|
||
|
|
message: '',
|
||
|
|
type: 'success',
|
||
|
|
duration: 3000
|
||
|
|
});
|
||
|
|
|
||
|
|
const show = ref(false);
|
||
|
|
const emit = defineEmits(['close']);
|
||
|
|
|
||
|
|
watch(() => props.message, (newVal) => {
|
||
|
|
if (newVal) {
|
||
|
|
show.value = true;
|
||
|
|
setTimeout(() => {
|
||
|
|
show.value = false;
|
||
|
|
setTimeout(() => {
|
||
|
|
emit('close');
|
||
|
|
}, 300);
|
||
|
|
}, props.duration);
|
||
|
|
}
|
||
|
|
}, { immediate: true });
|
||
|
|
</script>
|