You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
60 lines
1.5 KiB
TypeScript
60 lines
1.5 KiB
TypeScript
3 years ago
|
import { useCallback, useEffect, useRef } from "react";
|
||
2 years ago
|
import { CloseIcon } from "./icons";
|
||
4 years ago
|
import "./Toast.scss";
|
||
3 years ago
|
import { ToolButton } from "./ToolButton";
|
||
|
|
||
|
const DEFAULT_TOAST_TIMEOUT = 5000;
|
||
4 years ago
|
|
||
|
export const Toast = ({
|
||
|
message,
|
||
3 years ago
|
onClose,
|
||
3 years ago
|
closable = false,
|
||
|
// To prevent autoclose, pass duration as Infinity
|
||
|
duration = DEFAULT_TOAST_TIMEOUT,
|
||
4 years ago
|
}: {
|
||
|
message: string;
|
||
3 years ago
|
onClose: () => void;
|
||
3 years ago
|
closable?: boolean;
|
||
|
duration?: number;
|
||
4 years ago
|
}) => {
|
||
|
const timerRef = useRef<number>(0);
|
||
3 years ago
|
const shouldAutoClose = duration !== Infinity;
|
||
|
const scheduleTimeout = useCallback(() => {
|
||
|
if (!shouldAutoClose) {
|
||
|
return;
|
||
|
}
|
||
3 years ago
|
timerRef.current = window.setTimeout(() => onClose(), duration);
|
||
|
}, [onClose, duration, shouldAutoClose]);
|
||
4 years ago
|
|
||
|
useEffect(() => {
|
||
3 years ago
|
if (!shouldAutoClose) {
|
||
|
return;
|
||
|
}
|
||
4 years ago
|
scheduleTimeout();
|
||
|
return () => clearTimeout(timerRef.current);
|
||
3 years ago
|
}, [scheduleTimeout, message, duration, shouldAutoClose]);
|
||
4 years ago
|
|
||
3 years ago
|
const onMouseEnter = shouldAutoClose
|
||
|
? () => clearTimeout(timerRef?.current)
|
||
|
: undefined;
|
||
|
const onMouseLeave = shouldAutoClose ? scheduleTimeout : undefined;
|
||
4 years ago
|
return (
|
||
|
<div
|
||
|
className="Toast"
|
||
3 years ago
|
onMouseEnter={onMouseEnter}
|
||
|
onMouseLeave={onMouseLeave}
|
||
4 years ago
|
>
|
||
|
<p className="Toast__message">{message}</p>
|
||
3 years ago
|
{closable && (
|
||
|
<ToolButton
|
||
2 years ago
|
icon={CloseIcon}
|
||
3 years ago
|
aria-label="close"
|
||
|
type="icon"
|
||
3 years ago
|
onClick={onClose}
|
||
3 years ago
|
className="close"
|
||
|
/>
|
||
|
)}
|
||
4 years ago
|
</div>
|
||
|
);
|
||
|
};
|