Skip to content

Commit 377b6b2

Browse files
committed
fix: 优化 dashboard toast 自动消失
1 parent fe55327 commit 377b6b2

2 files changed

Lines changed: 31 additions & 2 deletions

File tree

dashboard/src/components/ui/toast.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ const ToastViewport = React.forwardRef<
1717
<ToastPrimitives.Viewport
1818
ref={ref}
1919
className={cn(
20-
"fixed z-[100] flex max-h-screen w-full gap-2 p-4",
20+
"fixed z-[100] flex max-h-screen w-full gap-2 p-4 pointer-events-none",
2121
isMobile
2222
? "top-0 left-0 right-0 flex-col items-center"
23-
: "bottom-0 right-0 flex-col-reverse sm:max-w-[420px]",
23+
: "top-0 right-0 flex-col sm:max-w-[420px]",
2424
className
2525
)}
2626
{...props}

dashboard/src/hooks/use-toast.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import type {
1010

1111
const TOAST_LIMIT = 5
1212
const TOAST_REMOVE_DELAY = 5000
13+
const TOAST_AUTO_DISMISS_DELAY = 2000
1314

1415
type ToasterToast = ToastProps & {
1516
id: string
@@ -55,6 +56,17 @@ interface State {
5556
}
5657

5758
const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>()
59+
const toastAutoDismissTimeouts = new Map<string, ReturnType<typeof setTimeout>>()
60+
61+
const clearAutoDismissTimeout = (toastId: string) => {
62+
const timeout = toastAutoDismissTimeouts.get(toastId)
63+
if (!timeout) {
64+
return
65+
}
66+
67+
clearTimeout(timeout)
68+
toastAutoDismissTimeouts.delete(toastId)
69+
}
5870

5971
const addToRemoveQueue = (toastId: string) => {
6072
if (toastTimeouts.has(toastId)) {
@@ -94,8 +106,11 @@ export const reducer = (state: State, action: Action): State => {
94106
// ! Side effects ! - This could be extracted into a dismissToast() action,
95107
// but I'll keep it here for simplicity
96108
if (toastId) {
109+
clearAutoDismissTimeout(toastId)
97110
addToRemoveQueue(toastId)
98111
} else {
112+
toastAutoDismissTimeouts.forEach((timeout) => clearTimeout(timeout))
113+
toastAutoDismissTimeouts.clear()
99114
state.toasts.forEach((toast) => {
100115
addToRemoveQueue(toast.id)
101116
})
@@ -115,11 +130,14 @@ export const reducer = (state: State, action: Action): State => {
115130
}
116131
case "REMOVE_TOAST":
117132
if (action.toastId === undefined) {
133+
toastAutoDismissTimeouts.forEach((timeout) => clearTimeout(timeout))
134+
toastAutoDismissTimeouts.clear()
118135
return {
119136
...state,
120137
toasts: [],
121138
}
122139
}
140+
clearAutoDismissTimeout(action.toastId)
123141
return {
124142
...state,
125143
toasts: state.toasts.filter((t) => t.id !== action.toastId),
@@ -142,6 +160,8 @@ type Toast = Omit<ToasterToast, "id">
142160

143161
function toast({ ...props }: Toast) {
144162
const id = genId()
163+
const autoDismissDuration =
164+
typeof props.duration === "number" ? props.duration : TOAST_AUTO_DISMISS_DELAY
145165

146166
const update = (props: ToasterToast) =>
147167
dispatch({
@@ -162,6 +182,15 @@ function toast({ ...props }: Toast) {
162182
},
163183
})
164184

185+
if (Number.isFinite(autoDismissDuration) && autoDismissDuration > 0) {
186+
const timeout = setTimeout(() => {
187+
toastAutoDismissTimeouts.delete(id)
188+
dispatch({ type: "DISMISS_TOAST", toastId: id })
189+
}, autoDismissDuration)
190+
191+
toastAutoDismissTimeouts.set(id, timeout)
192+
}
193+
165194
return {
166195
id: id,
167196
dismiss,

0 commit comments

Comments
 (0)