Skip to content

Commit d6879e7

Browse files
committed
feat(UI-1394): improve toast component
1 parent 87a7c64 commit d6879e7

File tree

1 file changed

+24
-23
lines changed

1 file changed

+24
-23
lines changed

src/components/molecules/toast.tsx

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, { useCallback, useEffect, useRef, useState } from "react";
1+
import React, { useCallback, useEffect, useLayoutEffect, useRef, useState } from "react";
22

33
import { AnimatePresence, motion } from "motion/react";
44
import { useTranslation } from "react-i18next";
@@ -20,16 +20,15 @@ export const Toast = () => {
2020
const [hoveredToasts, setHoveredToasts] = useState<{ [id: string]: boolean }>({});
2121

2222
const timerRefs = useRef<{ [key: string]: NodeJS.Timeout }>({});
23+
const toastRefs = useRef<{ [key: string]: HTMLDivElement | null }>({});
2324

24-
const startTimer = useCallback(
25-
(id: string) => {
26-
if (timerRefs.current[id]) {
27-
clearTimeout(timerRefs.current[id]);
28-
}
29-
timerRefs.current[id] = setTimeout(() => removeToast(id), 3000);
30-
},
31-
[removeToast]
32-
);
25+
const startTimer = useCallback((id: string) => {
26+
if (timerRefs.current[id]) {
27+
clearTimeout(timerRefs.current[id]);
28+
}
29+
timerRefs.current[id] = setTimeout(() => removeToast(id), 3000);
30+
// eslint-disable-next-line react-hooks/exhaustive-deps
31+
}, []);
3332

3433
const handleMouseEnter = useCallback((id: string) => {
3534
setHoveredToasts((prev) => ({ ...prev, [id]: true }));
@@ -38,30 +37,30 @@ export const Toast = () => {
3837
}
3938
}, []);
4039

41-
const handleMouseLeave = useCallback(
42-
(id: string) => {
43-
setHoveredToasts((prev) => ({ ...prev, [id]: false }));
44-
startTimer(id);
45-
},
46-
[startTimer]
47-
);
40+
const handleMouseLeave = useCallback((id: string) => {
41+
setHoveredToasts((prev) => ({ ...prev, [id]: false }));
42+
startTimer(id);
43+
// eslint-disable-next-line react-hooks/exhaustive-deps
44+
}, []);
4845

49-
useEffect(() => {
46+
useLayoutEffect(() => {
5047
const topToasts = toasts.filter((t) => t.position === "top-right");
51-
const bottomToasts = toasts.filter((t) => t.position !== "top-right");
48+
const bottomToasts = toasts.filter((t) => t.position === "default");
5249

5350
const newPositions: { [key: string]: { bottom?: number; top?: number } } = {};
54-
let topOffset = topToasts[0]?.offset || 80;
55-
let bottomOffset = bottomToasts[0]?.offset || 15;
5651

52+
let topOffset = topToasts[0]?.offset || 15;
5753
topToasts.forEach((toast) => {
5854
newPositions[toast.id] = { top: topOffset };
59-
topOffset += 80;
55+
const height = toastRefs.current[toast.id]?.offsetHeight || 80;
56+
topOffset += height + 10;
6057
});
6158

59+
let bottomOffset = bottomToasts[0]?.offset || 15;
6260
bottomToasts.forEach((toast) => {
6361
newPositions[toast.id] = { bottom: bottomOffset };
64-
bottomOffset += 95;
62+
const height = toastRefs.current[toast.id]?.offsetHeight || 95;
63+
bottomOffset += height + 10;
6564
});
6665

6766
setPositions(newPositions);
@@ -75,6 +74,7 @@ export const Toast = () => {
7574
});
7675

7776
return () => {
77+
// eslint-disable-next-line react-hooks/exhaustive-deps
7878
const timers = { ...timerRefs.current };
7979
Object.values(timers).forEach(clearTimeout);
8080
};
@@ -127,6 +127,7 @@ export const Toast = () => {
127127
key={id}
128128
onMouseEnter={() => handleMouseEnter(id)}
129129
onMouseLeave={() => handleMouseLeave(id)}
130+
ref={(el) => (toastRefs.current[id] = el)}
130131
style={{
131132
...positions[id],
132133
transition: "all 0.2s ease-out",

0 commit comments

Comments
 (0)