Skip to content

Instantly share code, notes, and snippets.

@vmagamedov
Created February 28, 2023 18:31
Show Gist options
  • Save vmagamedov/b2437373fea73997a1061e01807858b9 to your computer and use it in GitHub Desktop.
Save vmagamedov/b2437373fea73997a1061e01807858b9 to your computer and use it in GitHub Desktop.
nprogress alternative for showing page loading progress in SPA application
import { styled } from "@linaria/react";
import * as React from "react";
import { useLayoutEffect, useState } from "react";
import { useNavigation } from "react-router";
const Bar = styled.div<{ barPosition: number }>`
pointer-events: none;
opacity: ${(props) => (props.barPosition === 80 ? "1" : "0")};
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 2px;
transform: translateX(-100%) translateX(${(props) => `${props.barPosition}%`});
background: #0076ff;
transition: opacity 150ms 150ms ease-in,
transform ${(props) => (props.barPosition === 80 ? "30s" : "0s")} linear;
`;
const Peg = styled.div`
position: absolute;
right: 0px;
width: 100px;
height: 100%;
box-shadow: 0 0 10px #0076ff, 0 0 5px #0076ff;
transform: rotate(3deg) translate(0px, -4px);
`;
export function Progress() {
const navigation = useNavigation();
const [barPosition, setBarPosition] = useState(100);
useLayoutEffect(() => {
if (navigation.state === "loading") {
setBarPosition(20);
// progress will be shown after:
// 150ms (timeout)
// + 150ms (transition delay)
// + 150ms (transition duration)
const timeout = setTimeout(() => setBarPosition(80), 150);
return () => {
clearTimeout(timeout);
};
} else if (navigation.state === "idle") {
setBarPosition(100);
}
}, [navigation.state]);
return (
<Bar barPosition={barPosition}>
<Peg />
</Bar>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment