feat: improve collab error notification (#7741)
* identify cause * toast after dialog for error messages in collab * remove comment * shake tooltip instead for repeating collab errors * clear collab error * empty commit * simplify & fix reset race condition --------- Co-authored-by: dwelle <5153846+dwelle@users.noreply.github.com>pull/7693/head
parent
f207bd0a1c
commit
160440b860
@ -0,0 +1,35 @@
|
||||
@import "../../packages/excalidraw/css/variables.module.scss";
|
||||
|
||||
.excalidraw {
|
||||
.collab-errors-button {
|
||||
width: 26px;
|
||||
height: 26px;
|
||||
margin-inline-end: 1rem;
|
||||
|
||||
color: var(--color-danger);
|
||||
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.collab-errors-button-shake {
|
||||
animation: strong-shake 0.15s 6;
|
||||
}
|
||||
|
||||
@keyframes strong-shake {
|
||||
0% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
25% {
|
||||
transform: rotate(10deg);
|
||||
}
|
||||
50% {
|
||||
transform: rotate(0eg);
|
||||
}
|
||||
75% {
|
||||
transform: rotate(-10deg);
|
||||
}
|
||||
100% {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
import { Tooltip } from "../../packages/excalidraw/components/Tooltip";
|
||||
import { warning } from "../../packages/excalidraw/components/icons";
|
||||
import clsx from "clsx";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
|
||||
import "./CollabError.scss";
|
||||
import { atom } from "jotai";
|
||||
|
||||
type ErrorIndicator = {
|
||||
message: string | null;
|
||||
/** used to rerun the useEffect responsible for animation */
|
||||
nonce: number;
|
||||
};
|
||||
|
||||
export const collabErrorIndicatorAtom = atom<ErrorIndicator>({
|
||||
message: null,
|
||||
nonce: 0,
|
||||
});
|
||||
|
||||
const CollabError = ({ collabError }: { collabError: ErrorIndicator }) => {
|
||||
const [isAnimating, setIsAnimating] = useState(false);
|
||||
const clearAnimationRef = useRef<string | number | NodeJS.Timeout>();
|
||||
|
||||
useEffect(() => {
|
||||
setIsAnimating(true);
|
||||
clearAnimationRef.current = setTimeout(() => {
|
||||
setIsAnimating(false);
|
||||
}, 1000);
|
||||
|
||||
return () => {
|
||||
clearTimeout(clearAnimationRef.current);
|
||||
};
|
||||
}, [collabError.message, collabError.nonce]);
|
||||
|
||||
if (!collabError.message) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<Tooltip label={collabError.message} long={true}>
|
||||
<div
|
||||
className={clsx("collab-errors-button", {
|
||||
"collab-errors-button-shake": isAnimating,
|
||||
})}
|
||||
>
|
||||
{warning}
|
||||
</div>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
CollabError.displayName = "CollabError";
|
||||
|
||||
export default CollabError;
|
Loading…
Reference in New Issue