rewrite: toast stacking with daisyui toast container

- module-level reactive toast list in composables/toast (setToast signature unchanged, 13 call sites untouched)
- multiple toasts stack simultaneously in daisyUI toast container, each auto-dismisses (3s) with close button
- TransitionGroup enter/leave animation (transform/opacity, honors reduced-motion)
- drop provide/inject queue that blocked consecutive toasts
This commit is contained in:
Sakurasan
2026-08-30 01:54:57 +08:00
parent 1e07c5903f
commit 33f5e7b71a
4 changed files with 78 additions and 82 deletions
+26 -15
View File
@@ -1,24 +1,35 @@
import { inject } from 'vue'
import type { InjectionKey } from 'vue'
import { ref } from 'vue'
export type ToastType = 'info' | 'success' | 'error'
export type ToastMessage = {
message: string
type?: ToastType
duration?: number
export type ToastItem = {
id: number
message: string
type: ToastType
duration: number
}
export type ToastContext = {
setToast: (message: string, type?: ToastType, duration?: number) => void
// 模块级共享状态:所有活动 toast 堆叠展示,互不阻塞
const toasts = ref<ToastItem[]>([])
let seed = 0
function dismiss(id: number) {
toasts.value = toasts.value.filter(t => t.id !== id)
}
export const ToastKey: InjectionKey<ToastContext> = Symbol('toast')
export function setToast(message: string, type: ToastType = 'info', duration = 3000) {
const id = ++seed
toasts.value.push({ id, message, type, duration })
if (duration > 0) {
setTimeout(() => dismiss(id), duration)
}
}
export function useToast(): ToastContext {
const ctx = inject(ToastKey)
if (!ctx) {
throw new Error('ToastContext 未提供:请在 App 根组件 provide(ToastKey, ...)')
}
return ctx
export function useToast() {
return { setToast }
}
// 供 Toast 组件渲染使用
export function useToasts() {
return { toasts, dismiss }
}