Skip to content

Commit

Permalink
feat: Add global loading indicator to top nav (#176)
Browse files Browse the repository at this point in the history
* feat: Add global loading indicator to top nav

* chore: Apply some of Brook's suggestions to global-loading code
  • Loading branch information
gustavoguichard authored Feb 5, 2024
1 parent d22a79f commit f0c65a2
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 0 deletions.
2 changes: 2 additions & 0 deletions app/root.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -128,6 +129,7 @@ function Document({
: "bg-white text-gray-900 dark:bg-gray-900 dark:text-gray-200",
)}
>
<GlobalLoading />
{children}
<ScrollRestoration />
<Scripts />
Expand Down
46 changes: 46 additions & 0 deletions app/ui/global-loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { useEffect, useRef, useState } from "react";
import { useNavigation } from "@remix-run/react";
import cx from "clsx";

export function GlobalLoading() {
let transition = useNavigation();
let active = transition.state !== "idle";

let ref = useRef<HTMLDivElement>(null);
let [animating, setAnimating] = useState(false);

useEffect(() => {
if (!ref.current) return;

Promise.allSettled(
ref.current.getAnimations().map(({ finished }) => finished),
).then(() => {
if (!active) setAnimating(false);
});

if (active) {
let id = setTimeout(() => setAnimating(true), 100);
return () => clearTimeout(id);
}
}, [active]);

return (
<div
role="progressbar"
aria-hidden={!active}
aria-valuetext={active ? "Loading" : undefined}
className="fixed inset-x-0 left-0 top-0 z-50 h-1 animate-pulse"
>
<div
ref={ref}
className={cx(
"h-full bg-gradient-to-r from-blue-brand to-aqua-brand transition-all duration-500 ease-in-out",
transition.state === "idle" &&
(animating ? "w-full" : "w-0 opacity-0 transition-none"),
transition.state === "submitting" && "w-4/12",
transition.state === "loading" && "w-10/12",
)}
/>
</div>
);
}

0 comments on commit f0c65a2

Please sign in to comment.