120 lines
2.1 KiB
Vue
120 lines
2.1 KiB
Vue
<template>
|
|
<transition-group name="slide" tag="div">
|
|
<div
|
|
v-for="(notification, index) in notifications"
|
|
:key="notification.id"
|
|
class="notification"
|
|
:class="position"
|
|
>
|
|
<span>{{ notification.message }}</span>
|
|
</div>
|
|
</transition-group>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, reactive, onMounted, watchEffect } from "vue";
|
|
|
|
let id = 0;
|
|
|
|
const props = defineProps({
|
|
position: {
|
|
type: String,
|
|
default: "top-right",
|
|
validator: (value) =>
|
|
["top-right", "top-left", "bottom-right", "bottom-left"].includes(value),
|
|
},
|
|
duration: {
|
|
type: Number,
|
|
default: 3000,
|
|
},
|
|
});
|
|
|
|
const notifications = reactive([]);
|
|
|
|
const addNotification = (message) => {
|
|
const notification = {
|
|
id: id++,
|
|
message,
|
|
};
|
|
|
|
notifications.push(notification);
|
|
|
|
setTimeout(() => {
|
|
closeNotification(notifications.indexOf(notification));
|
|
}, props.duration);
|
|
};
|
|
|
|
const closeNotification = (index) => {
|
|
if (index !== -1) {
|
|
notifications.splice(index, 1);
|
|
}
|
|
};
|
|
|
|
defineExpose({
|
|
addNotification,
|
|
closeNotification,
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.slide-enter-active,
|
|
.slide-leave-active {
|
|
transition: transform 0.3s ease-out, opacity 0.3s ease-out;
|
|
}
|
|
|
|
.slide-enter-from,
|
|
.slide-leave-to {
|
|
transform: translateX(100%);
|
|
opacity: 0;
|
|
}
|
|
|
|
.slide-enter-to,
|
|
.slide-leave-from {
|
|
transform: translateX(0);
|
|
opacity: 1;
|
|
}
|
|
|
|
.notification {
|
|
position: fixed;
|
|
padding: 0.8em;
|
|
background: url('../../assets/img/task/msg-bg.png') no-repeat;
|
|
background-size: 100% 100%;
|
|
color: #721c24;
|
|
/* border: solid 1px #f5c6cb; */
|
|
border-radius: 0.25rem;
|
|
min-width: 304px;
|
|
min-height: 80px; /* set minimum height */
|
|
display: flex;
|
|
font-size: 14px;
|
|
font-family: Arial;
|
|
font-weight: 400;
|
|
color: #ffffff;
|
|
align-items: center;
|
|
justify-content: center;
|
|
text-align: center;
|
|
white-space: normal;
|
|
word-wrap: break-word;
|
|
|
|
}
|
|
|
|
.notification.top-right {
|
|
right: 50px;
|
|
top: 80px;
|
|
}
|
|
|
|
.notification.top-left {
|
|
left: 0;
|
|
top: 0;
|
|
}
|
|
|
|
.notification.bottom-right {
|
|
right: 0;
|
|
bottom: 0;
|
|
}
|
|
|
|
.notification.bottom-left {
|
|
left: 0;
|
|
bottom: 0;
|
|
}
|
|
</style>
|