2022-07-26 09:51:19 +00:00
|
|
|
<template>
|
|
|
|
<TransitionGroup name="toast" tag="ul">
|
|
|
|
<li v-for="message in messages" :key="message.id">
|
2022-12-02 16:17:37 +00:00
|
|
|
<MessageToast :message="message" @dismiss="removeMessage(message)" />
|
2022-07-26 09:51:19 +00:00
|
|
|
</li>
|
|
|
|
</TransitionGroup>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script lang="ts" setup>
|
|
|
|
import { ref } from 'vue'
|
2023-04-17 20:13:11 +00:00
|
|
|
import { uuid } from '@/utils'
|
2022-07-26 14:59:19 +00:00
|
|
|
import MessageToast from '@/components/ui/MessageToast.vue'
|
2022-07-26 09:51:19 +00:00
|
|
|
|
|
|
|
const messages = ref<ToastMessage[]>([])
|
|
|
|
|
2022-11-29 10:18:58 +00:00
|
|
|
const addMessage = (type: 'info' | 'success' | 'warning' | 'danger', content: string, timeout = 5) => {
|
2022-07-26 09:51:19 +00:00
|
|
|
messages.value.push({
|
|
|
|
type,
|
|
|
|
content,
|
2023-04-17 20:13:11 +00:00
|
|
|
timeout,
|
|
|
|
id: uuid()
|
2022-07-26 09:51:19 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2024-01-24 22:39:47 +00:00
|
|
|
const removeMessage = (message: ToastMessage) => (messages.value = messages.value.filter(({ id }) => id !== message.id))
|
2022-07-26 09:51:19 +00:00
|
|
|
|
|
|
|
const info = (content: string, timeout?: number) => addMessage('info', content, timeout)
|
|
|
|
const success = (content: string, timeout?: number) => addMessage('success', content, timeout)
|
|
|
|
const warning = (content: string, timeout?: number) => addMessage('warning', content, timeout)
|
|
|
|
const error = (content: string, timeout?: number) => addMessage('danger', content, timeout)
|
|
|
|
|
|
|
|
defineExpose({ info, success, warning, error })
|
|
|
|
</script>
|
|
|
|
|
2024-04-04 20:13:35 +00:00
|
|
|
<style lang="postcss" scoped>
|
2022-07-26 09:51:19 +00:00
|
|
|
ul {
|
|
|
|
position: fixed;
|
|
|
|
z-index: 9999;
|
|
|
|
right: 0;
|
|
|
|
top: 10px;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
align-items: flex-end;
|
|
|
|
gap: 5px;
|
|
|
|
}
|
|
|
|
|
|
|
|
.toast-enter-active {
|
|
|
|
opacity: 1;
|
|
|
|
transition: all 0.2s ease-in;
|
|
|
|
}
|
|
|
|
|
|
|
|
.toast-leave-active {
|
|
|
|
opacity: 0;
|
|
|
|
transition: all 0.2s ease-out;
|
|
|
|
}
|
|
|
|
|
|
|
|
.toast-enter-from, .toast-leave-to {
|
|
|
|
opacity: 0;
|
|
|
|
transform: translateX(100px);
|
|
|
|
}
|
|
|
|
</style>
|