|
@@ -1,34 +1,59 @@
|
|
|
import { useCallback, useEffect, useRef } from "react";
|
|
|
-import { TOAST_TIMEOUT } from "../constants";
|
|
|
+import { close } from "./icons";
|
|
|
import "./Toast.scss";
|
|
|
+import { ToolButton } from "./ToolButton";
|
|
|
+
|
|
|
+const DEFAULT_TOAST_TIMEOUT = 5000;
|
|
|
|
|
|
export const Toast = ({
|
|
|
message,
|
|
|
clearToast,
|
|
|
+ closable = false,
|
|
|
+ // To prevent autoclose, pass duration as Infinity
|
|
|
+ duration = DEFAULT_TOAST_TIMEOUT,
|
|
|
}: {
|
|
|
message: string;
|
|
|
clearToast: () => void;
|
|
|
+ closable?: boolean;
|
|
|
+ duration?: number;
|
|
|
}) => {
|
|
|
const timerRef = useRef<number>(0);
|
|
|
-
|
|
|
- const scheduleTimeout = useCallback(
|
|
|
- () =>
|
|
|
- (timerRef.current = window.setTimeout(() => clearToast(), TOAST_TIMEOUT)),
|
|
|
- [clearToast],
|
|
|
- );
|
|
|
+ const shouldAutoClose = duration !== Infinity;
|
|
|
+ const scheduleTimeout = useCallback(() => {
|
|
|
+ if (!shouldAutoClose) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ timerRef.current = window.setTimeout(() => clearToast(), duration);
|
|
|
+ }, [clearToast, duration, shouldAutoClose]);
|
|
|
|
|
|
useEffect(() => {
|
|
|
+ if (!shouldAutoClose) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
scheduleTimeout();
|
|
|
return () => clearTimeout(timerRef.current);
|
|
|
- }, [scheduleTimeout, message]);
|
|
|
+ }, [scheduleTimeout, message, duration, shouldAutoClose]);
|
|
|
|
|
|
+ const onMouseEnter = shouldAutoClose
|
|
|
+ ? () => clearTimeout(timerRef?.current)
|
|
|
+ : undefined;
|
|
|
+ const onMouseLeave = shouldAutoClose ? scheduleTimeout : undefined;
|
|
|
return (
|
|
|
<div
|
|
|
className="Toast"
|
|
|
- onMouseEnter={() => clearTimeout(timerRef?.current)}
|
|
|
- onMouseLeave={scheduleTimeout}
|
|
|
+ onMouseEnter={onMouseEnter}
|
|
|
+ onMouseLeave={onMouseLeave}
|
|
|
>
|
|
|
<p className="Toast__message">{message}</p>
|
|
|
+ {closable && (
|
|
|
+ <ToolButton
|
|
|
+ icon={close}
|
|
|
+ aria-label="close"
|
|
|
+ type="icon"
|
|
|
+ onClick={clearToast}
|
|
|
+ className="close"
|
|
|
+ />
|
|
|
+ )}
|
|
|
</div>
|
|
|
);
|
|
|
};
|