CollabError.tsx 1.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455
  1. import { Tooltip } from "@excalidraw/excalidraw/components/Tooltip";
  2. import { warning } from "@excalidraw/excalidraw/components/icons";
  3. import clsx from "clsx";
  4. import { useEffect, useRef, useState } from "react";
  5. import { atom } from "../app-jotai";
  6. import "./CollabError.scss";
  7. type ErrorIndicator = {
  8. message: string | null;
  9. /** used to rerun the useEffect responsible for animation */
  10. nonce: number;
  11. };
  12. export const collabErrorIndicatorAtom = atom<ErrorIndicator>({
  13. message: null,
  14. nonce: 0,
  15. });
  16. const CollabError = ({ collabError }: { collabError: ErrorIndicator }) => {
  17. const [isAnimating, setIsAnimating] = useState(false);
  18. const clearAnimationRef = useRef<string | number>(0);
  19. useEffect(() => {
  20. setIsAnimating(true);
  21. clearAnimationRef.current = window.setTimeout(() => {
  22. setIsAnimating(false);
  23. }, 1000);
  24. return () => {
  25. window.clearTimeout(clearAnimationRef.current);
  26. };
  27. }, [collabError.message, collabError.nonce]);
  28. if (!collabError.message) {
  29. return null;
  30. }
  31. return (
  32. <Tooltip label={collabError.message} long={true}>
  33. <div
  34. className={clsx("collab-errors-button", {
  35. "collab-errors-button-shake": isAnimating,
  36. })}
  37. >
  38. {warning}
  39. </div>
  40. </Tooltip>
  41. );
  42. };
  43. CollabError.displayName = "CollabError";
  44. export default CollabError;