Add toast notification system: implement useToast composable and ToastContainer component

This commit is contained in:
lucast committed 2025-12-05 17:39:37 +01:00
1 parent 46951be40f
commit 2b368cede4
2 files changed
+107

No files matched your search

+30
View File
@@ -0,0 +1,30 @@
type Toast = {
id: number
message: string
type?: "success" | "error" | "info"
}
const toasts = ref<Toast[]>([])
export const useToast = () => {
const show = (
message: string,
type: Toast["type"] = "info",
duration = 5 * 1000
): number => {
const id = toasts.value.length + 1
toasts.value.push({ id, message, type })
setTimeout(() => {
remove(id)
}, duration)
return id
}
const remove = (id: number) => {
toasts.value = toasts.value.filter((t) => t.id != id)
}
return { toasts, show, remove }
}
+77
View File
@@ -0,0 +1,77 @@
<script setup lang="ts">
const { toasts, remove } = useToast()
</script>
<template>
<div class="toast-container">
<TransitionGroup name="toast">
<div
v-for="toast in toasts"
:key="toast.id"
class="toast"
:class="[toast.type]"
@click="remove(toast.id)"
>
{{ toast.message }}
</div>
</TransitionGroup>
</div>
</template>
<style lang="scss" scoped>
@use "@/styles/variables" as *;
.toast-container {
position: fixed;
bottom: 0;
right: 0;
z-index: 100;
padding: 20px;
display: flex;
flex-direction: column;
gap: 10px;
}
.toast {
background-color: $color-background;
border: 1px solid $color-border;
border-radius: $standard-border-radius;
padding: 10px 16px;
min-width: 200px;
cursor: pointer;
transition: transform 0.2s ease, opacity 0.2s ease;
}
.toast-enter-from {
opacity: 0;
transform: translateX(50px);
}
.toast-enter-active {
transition: all 0.3s ease-out;
}
.toast-enter-to {
opacity: 1;
transform: translateX(0);
}
.toast-leave-from {
opacity: 1;
transform: translateX(0);
}
.toast-leave-active {
transition: all 0.3s ease-out;
}
.toast-leave-to {
opacity: 0;
transform: translateX(50px);
}
</style>