From dad1da471219e5e0704fb0b40d2067cb1a63b470 Mon Sep 17 00:00:00 2001 From: Guga Guichard Date: Mon, 5 Feb 2024 09:08:31 -0300 Subject: [PATCH] feat: Add global loading indicator to top nav --- app/root.tsx | 2 ++ app/ui/global-loading.tsx | 42 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 app/ui/global-loading.tsx diff --git a/app/root.tsx b/app/root.tsx index 2d2c6457..e889f1e9 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -25,6 +25,7 @@ import { parseColorScheme } from "~/lib/color-scheme.server"; import iconsHref from "~/icons.svg"; import cx from "clsx"; import { canUseDOM } from "./ui/primitives/utils"; +import { GlobalLoading } from "./ui/global-loading"; export async function loader({ request }: LoaderFunctionArgs) { removeTrailingSlashes(request); @@ -128,6 +129,7 @@ function Document({ : "bg-white text-gray-900 dark:bg-gray-900 dark:text-gray-200", )} > + {children} diff --git a/app/ui/global-loading.tsx b/app/ui/global-loading.tsx new file mode 100644 index 00000000..a1b8b3eb --- /dev/null +++ b/app/ui/global-loading.tsx @@ -0,0 +1,42 @@ +import * as React from "react"; +import { useNavigation } from "@remix-run/react"; +import cx from "clsx"; + +export function GlobalLoading() { + const transition = useNavigation(); + const active = transition.state !== "idle"; + + const ref = React.useRef(null); + const [animationComplete, setAnimationComplete] = React.useState(true); + + React.useEffect(() => { + if (!ref.current) return; + if (active) setAnimationComplete(false); + + Promise.allSettled( + ref.current.getAnimations().map(({ finished }) => finished), + ).then(() => !active && setAnimationComplete(true)); + }, [active]); + + return ( +
+
+
+ ); +}