feat: make toast closable and allow custom duration (#5308)
* feat: make toast closable and allow custom duration * use Infinity to keep prevent auto close * rename to DEFAULT_TOAST_TIMEOUT and move to toast.tsx * fix * set closable as false by default and fix design * tweak css * reuse variables Co-authored-by: dwelle <luzar.david@gmail.com>
This commit is contained in:
parent
dac8dda4d4
commit
76a5bb060e
@ -2,6 +2,9 @@
|
|||||||
|
|
||||||
.excalidraw {
|
.excalidraw {
|
||||||
.Toast {
|
.Toast {
|
||||||
|
$closeButtonSize: 1.2rem;
|
||||||
|
$closeButtonPadding: 0.4rem;
|
||||||
|
|
||||||
animation: fade-in 0.5s;
|
animation: fade-in 0.5s;
|
||||||
background-color: var(--button-gray-1);
|
background-color: var(--button-gray-1);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
@ -15,11 +18,24 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
width: 300px;
|
width: 300px;
|
||||||
z-index: 999999;
|
z-index: 999999;
|
||||||
}
|
|
||||||
|
|
||||||
.Toast__message {
|
.Toast__message {
|
||||||
color: var(--popup-text-color);
|
padding: 0 $closeButtonSize + ($closeButtonPadding);
|
||||||
white-space: pre-wrap;
|
color: var(--popup-text-color);
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
padding: $closeButtonPadding;
|
||||||
|
|
||||||
|
.ToolIcon__icon {
|
||||||
|
width: $closeButtonSize;
|
||||||
|
height: $closeButtonSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes fade-in {
|
@keyframes fade-in {
|
||||||
|
@ -1,34 +1,59 @@
|
|||||||
import { useCallback, useEffect, useRef } from "react";
|
import { useCallback, useEffect, useRef } from "react";
|
||||||
import { TOAST_TIMEOUT } from "../constants";
|
import { close } from "./icons";
|
||||||
import "./Toast.scss";
|
import "./Toast.scss";
|
||||||
|
import { ToolButton } from "./ToolButton";
|
||||||
|
|
||||||
|
const DEFAULT_TOAST_TIMEOUT = 5000;
|
||||||
|
|
||||||
export const Toast = ({
|
export const Toast = ({
|
||||||
message,
|
message,
|
||||||
clearToast,
|
clearToast,
|
||||||
|
closable = false,
|
||||||
|
// To prevent autoclose, pass duration as Infinity
|
||||||
|
duration = DEFAULT_TOAST_TIMEOUT,
|
||||||
}: {
|
}: {
|
||||||
message: string;
|
message: string;
|
||||||
clearToast: () => void;
|
clearToast: () => void;
|
||||||
|
closable?: boolean;
|
||||||
|
duration?: number;
|
||||||
}) => {
|
}) => {
|
||||||
const timerRef = useRef<number>(0);
|
const timerRef = useRef<number>(0);
|
||||||
|
const shouldAutoClose = duration !== Infinity;
|
||||||
const scheduleTimeout = useCallback(
|
const scheduleTimeout = useCallback(() => {
|
||||||
() =>
|
if (!shouldAutoClose) {
|
||||||
(timerRef.current = window.setTimeout(() => clearToast(), TOAST_TIMEOUT)),
|
return;
|
||||||
[clearToast],
|
}
|
||||||
);
|
timerRef.current = window.setTimeout(() => clearToast(), duration);
|
||||||
|
}, [clearToast, duration, shouldAutoClose]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
if (!shouldAutoClose) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
scheduleTimeout();
|
scheduleTimeout();
|
||||||
return () => clearTimeout(timerRef.current);
|
return () => clearTimeout(timerRef.current);
|
||||||
}, [scheduleTimeout, message]);
|
}, [scheduleTimeout, message, duration, shouldAutoClose]);
|
||||||
|
|
||||||
|
const onMouseEnter = shouldAutoClose
|
||||||
|
? () => clearTimeout(timerRef?.current)
|
||||||
|
: undefined;
|
||||||
|
const onMouseLeave = shouldAutoClose ? scheduleTimeout : undefined;
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="Toast"
|
className="Toast"
|
||||||
onMouseEnter={() => clearTimeout(timerRef?.current)}
|
onMouseEnter={onMouseEnter}
|
||||||
onMouseLeave={scheduleTimeout}
|
onMouseLeave={onMouseLeave}
|
||||||
>
|
>
|
||||||
<p className="Toast__message">{message}</p>
|
<p className="Toast__message">{message}</p>
|
||||||
|
{closable && (
|
||||||
|
<ToolButton
|
||||||
|
icon={close}
|
||||||
|
aria-label="close"
|
||||||
|
type="icon"
|
||||||
|
onClick={clearToast}
|
||||||
|
className="close"
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -116,7 +116,6 @@ export const IMAGE_RENDER_TIMEOUT = 500;
|
|||||||
export const TAP_TWICE_TIMEOUT = 300;
|
export const TAP_TWICE_TIMEOUT = 300;
|
||||||
export const TOUCH_CTX_MENU_TIMEOUT = 500;
|
export const TOUCH_CTX_MENU_TIMEOUT = 500;
|
||||||
export const TITLE_TIMEOUT = 10000;
|
export const TITLE_TIMEOUT = 10000;
|
||||||
export const TOAST_TIMEOUT = 5000;
|
|
||||||
export const VERSION_TIMEOUT = 30000;
|
export const VERSION_TIMEOUT = 30000;
|
||||||
export const SCROLL_TIMEOUT = 100;
|
export const SCROLL_TIMEOUT = 100;
|
||||||
export const ZOOM_STEP = 0.1;
|
export const ZOOM_STEP = 0.1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user