ToastHost.vue
2.08 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
<script setup>
/**
* ToastHost —— 应用根挂载一次,渲染 use-toast 的受控队列。只读队列、不写入;
* 写入一律走 `useToast()`。每条 toast 可手动关闭(点 × 调 dismiss)。
*/
import { useToast, useToastQueue } from '../composables/use-toast.js'
const toasts = useToastQueue()
const { dismiss } = useToast()
</script>
<template>
<Teleport to="body">
<div
class="drama-toast-host"
role="region"
aria-live="polite"
>
<div
v-for="t in toasts"
:key="t.id"
class="drama-toast"
:class="`drama-toast--${t.type}`"
role="status"
>
<span class="drama-toast__msg">{{ t.message }}</span>
<button
class="drama-toast__close"
type="button"
aria-label="Dismiss"
@click="dismiss(t.id)"
>
×
</button>
</div>
</div>
</Teleport>
</template>
<style scoped>
.drama-toast-host {
position: fixed;
top: var(--drama-space-lg);
right: var(--drama-space-lg);
display: flex;
flex-direction: column;
gap: var(--drama-space-sm);
z-index: 1100;
pointer-events: none;
}
.drama-toast {
display: flex;
align-items: center;
gap: var(--drama-space-md);
min-width: 240px;
max-width: 360px;
padding: var(--drama-space-md) var(--drama-space-lg);
border-radius: var(--drama-radius-md);
border-left: 4px solid var(--drama-color-border);
background-color: var(--drama-color-surface);
color: var(--drama-color-text);
box-shadow: var(--drama-shadow-md);
font-family: var(--drama-font-family-body);
font-size: var(--drama-font-size-sm);
pointer-events: auto;
}
.drama-toast--success {
border-left-color: var(--drama-color-success);
}
.drama-toast--error {
border-left-color: var(--drama-color-danger);
}
.drama-toast--info {
border-left-color: var(--drama-color-info);
}
.drama-toast__msg {
flex: 1;
}
.drama-toast__close {
background: transparent;
border: none;
color: var(--drama-color-text-muted);
font-size: var(--drama-font-size-lg);
line-height: 1;
cursor: pointer;
}
</style>