diff options
| author | kj_sh604 | 2026-03-15 16:19:35 -0400 |
|---|---|---|
| committer | kj_sh604 | 2026-03-15 16:19:35 -0400 |
| commit | 6ec259a0e71174651bae95d4628138bf6fd68742 (patch) | |
| tree | 5e33c6a5ec091ecabfcb257fdc7b6a88ed8754ac /packages/excalidraw/components/Toast.tsx | |
| parent | 16c8578b15c727f22921f8a80a56ee4d4e7f2272 (diff) | |
refactor: packages/
Diffstat (limited to 'packages/excalidraw/components/Toast.tsx')
| -rw-r--r-- | packages/excalidraw/components/Toast.tsx | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/packages/excalidraw/components/Toast.tsx b/packages/excalidraw/components/Toast.tsx new file mode 100644 index 0000000..d99c9f6 --- /dev/null +++ b/packages/excalidraw/components/Toast.tsx @@ -0,0 +1,63 @@ +import type { CSSProperties } from "react"; +import { useCallback, useEffect, useRef } from "react"; +import { CloseIcon } from "./icons"; +import "./Toast.scss"; +import { ToolButton } from "./ToolButton"; + +const DEFAULT_TOAST_TIMEOUT = 5000; + +export const Toast = ({ + message, + onClose, + closable = false, + // To prevent autoclose, pass duration as Infinity + duration = DEFAULT_TOAST_TIMEOUT, + style, +}: { + message: string; + onClose: () => void; + closable?: boolean; + duration?: number; + style?: CSSProperties; +}) => { + const timerRef = useRef<number>(0); + const shouldAutoClose = duration !== Infinity; + const scheduleTimeout = useCallback(() => { + if (!shouldAutoClose) { + return; + } + timerRef.current = window.setTimeout(() => onClose(), duration); + }, [onClose, duration, shouldAutoClose]); + + useEffect(() => { + if (!shouldAutoClose) { + return; + } + scheduleTimeout(); + return () => clearTimeout(timerRef.current); + }, [scheduleTimeout, message, duration, shouldAutoClose]); + + const onMouseEnter = shouldAutoClose + ? () => clearTimeout(timerRef?.current) + : undefined; + const onMouseLeave = shouldAutoClose ? scheduleTimeout : undefined; + return ( + <div + className="Toast" + onMouseEnter={onMouseEnter} + onMouseLeave={onMouseLeave} + style={style} + > + <p className="Toast__message">{message}</p> + {closable && ( + <ToolButton + icon={CloseIcon} + aria-label="close" + type="icon" + onClick={onClose} + className="close" + /> + )} + </div> + ); +}; |
