Skip to content

Commit 3f0b1c7

Browse files
authored
fix: UTC-569: Toast 'Annotation saved successfully' does not auto-dismiss and persists across page navigation (#9380)
1 parent e735b14 commit 3f0b1c7

File tree

1 file changed

+12
-10
lines changed

1 file changed

+12
-10
lines changed

web/libs/ui/src/lib/toast/toast.tsx

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { createContext, type FC, type ReactNode, useCallback, useContext, useState, useRef } from "react";
1+
import { createContext, type FC, type ReactNode, useCallback, useContext, useState } from "react";
22
import * as ToastPrimitive from "@radix-ui/react-toast";
33
import styles from "./toast.module.scss";
44
import clsx from "clsx";
@@ -119,7 +119,6 @@ export const useToast = () => {
119119

120120
export const ToastProvider: FC<ToastProviderWithTypes> = ({ swipeDirection = "down", children, type, ...props }) => {
121121
const [toastMessage, setToastMessage] = useState<ToastShowArgs | null>();
122-
const timerRef = useRef<NodeJS.Timeout>();
123122

124123
const defaultDuration = 4000;
125124
const duration = toastMessage?.duration ?? defaultDuration;
@@ -130,20 +129,21 @@ export const ToastProvider: FC<ToastProviderWithTypes> = ({ swipeDirection = "do
130129
if (id && current.id !== id) return current;
131130
return null;
132131
});
133-
if (timerRef.current) clearTimeout(timerRef.current);
134132
}, []);
135133

136-
const show = ({ message, type, duration = defaultDuration, id }: ToastShowArgs) => {
137-
if (timerRef.current) clearTimeout(timerRef.current);
138-
134+
const show = useCallback(({ message, type, duration = defaultDuration, id }: ToastShowArgs) => {
139135
const toastId = id ?? nanoid();
140136
setToastMessage({ message, type, duration, id: toastId });
137+
return toastId;
138+
}, []);
141139

142-
if (duration >= 0) {
143-
timerRef.current = setTimeout(() => dismiss(toastId), duration);
140+
// Handle Radix UI's onOpenChange to sync when toast closes
141+
const handleOpenChange = useCallback((open: boolean) => {
142+
if (!open) {
143+
setToastMessage(null);
144144
}
145-
return toastId;
146-
};
145+
}, []);
146+
147147
const toastType = toastMessage?.type ?? type ?? ToastType.info;
148148
return (
149149
<ToastContext.Provider value={{ show, dismiss }}>
@@ -155,6 +155,8 @@ export const ToastProvider: FC<ToastProviderWithTypes> = ({ swipeDirection = "do
155155
[styles.messageToast_alertError]: toastType === ToastType.alertError,
156156
})}
157157
open={!!toastMessage?.message}
158+
onOpenChange={handleOpenChange}
159+
duration={duration}
158160
action={
159161
<ToastAction onClose={() => setToastMessage(null)} altText="x">
160162
<IconCross />

0 commit comments

Comments
 (0)