feat: Page loading indicator (#10195)
parent
64147d3618
commit
2ac709630f
|
@ -58,6 +58,7 @@
|
|||
"@radix-ui/react-tooltip": "^1.0.0",
|
||||
"@stripe/react-stripe-js": "^1.10.0",
|
||||
"@stripe/stripe-js": "^1.35.0",
|
||||
"@tanem/react-nprogress": "^5.0.44",
|
||||
"@tanstack/react-query": "^4.3.9",
|
||||
"@tremor/react": "^2.0.0",
|
||||
"@types/turndown": "^5.0.1",
|
||||
|
|
|
@ -0,0 +1,80 @@
|
|||
import { useNProgress } from "@tanem/react-nprogress";
|
||||
import type { NextRouter } from "next/router";
|
||||
import type { PropsWithChildren } from "react";
|
||||
import { useEffect, useState, forwardRef } from "react";
|
||||
|
||||
import { classNames } from "@calcom/lib";
|
||||
|
||||
interface NProgressOptions {
|
||||
isAnimating: boolean;
|
||||
}
|
||||
|
||||
export type NProgressProps = PropsWithChildren<NProgressOptions>;
|
||||
|
||||
const NProgress = forwardRef<HTMLDivElement, NProgressProps>(({ isAnimating, ...rest }, ref) => {
|
||||
const { animationDuration, isFinished, progress } = useNProgress({
|
||||
isAnimating,
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
{...rest}
|
||||
ref={ref}
|
||||
className={classNames("fixed left-0 top-0 w-full", isFinished ? "opacity-0" : "opacity-100")}
|
||||
style={{
|
||||
transition: `opacity ${animationDuration}ms linear`,
|
||||
}}>
|
||||
<div
|
||||
className="bg-brand-emphasis h-0.5 w-full"
|
||||
style={{
|
||||
marginLeft: `${(-1 + progress) * 100}%`,
|
||||
transition: `margin-left ${animationDuration}ms linear`,
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
|
||||
NProgress.displayName = "NProgress";
|
||||
|
||||
export const NProgressNextRouter = ({ router }: { router: NextRouter }) => {
|
||||
const [state, setState] = useState({
|
||||
isRouteChanging: false,
|
||||
loadingKey: 0,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
const handleRouteChangeStart = () => {
|
||||
setState((prevState) => ({
|
||||
...prevState,
|
||||
isRouteChanging: true,
|
||||
loadingKey: prevState.loadingKey ^ 1,
|
||||
}));
|
||||
};
|
||||
|
||||
const handleRouteChangeEnd = () => {
|
||||
setState((prevState) => ({
|
||||
...prevState,
|
||||
isRouteChanging: false,
|
||||
}));
|
||||
};
|
||||
|
||||
router.events.on("routeChangeStart", handleRouteChangeStart);
|
||||
router.events.on("routeChangeComplete", handleRouteChangeEnd);
|
||||
router.events.on("routeChangeError", handleRouteChangeEnd);
|
||||
|
||||
return () => {
|
||||
router.events.off("routeChangeStart", handleRouteChangeStart);
|
||||
router.events.off("routeChangeComplete", handleRouteChangeEnd);
|
||||
router.events.off("routeChangeError", handleRouteChangeEnd);
|
||||
};
|
||||
}, [router.events]);
|
||||
|
||||
const isAnimating = state.isRouteChanging;
|
||||
|
||||
return (
|
||||
<>
|
||||
<NProgress isAnimating={isAnimating} key={state.loadingKey} />
|
||||
</>
|
||||
);
|
||||
};
|
|
@ -80,6 +80,7 @@ import {
|
|||
} from "@calcom/ui/components/icon";
|
||||
|
||||
import FreshChatProvider from "../ee/support/lib/freshchat/FreshChatProvider";
|
||||
import { NProgressNextRouter } from "./NProgressPageIndicator";
|
||||
import { TeamInviteBadge } from "./TeamInviteBadge";
|
||||
|
||||
// need to import without ssr to prevent hydration errors
|
||||
|
@ -162,6 +163,7 @@ function useRedirectToOnboardingIfNeeded() {
|
|||
}
|
||||
|
||||
const Layout = (props: LayoutProps) => {
|
||||
const router = useRouter();
|
||||
const pageTitle = typeof props.heading === "string" && !props.title ? props.heading : props.title;
|
||||
const bannerRef = useRef<HTMLDivElement | null>(null);
|
||||
const [bannersHeight, setBannersHeight] = useState<number>(0);
|
||||
|
@ -201,6 +203,7 @@ const Layout = (props: LayoutProps) => {
|
|||
<TimezoneChangeDialog />
|
||||
<div className="flex min-h-screen flex-col">
|
||||
<div ref={bannerRef} className="sticky top-0 z-10 w-full divide-y divide-black">
|
||||
<NProgressNextRouter router={router} />
|
||||
<TeamsUpgradeBanner />
|
||||
<OrgUpgradeBanner />
|
||||
<ImpersonatingBanner />
|
||||
|
|
102
yarn.lock
102
yarn.lock
|
@ -124,25 +124,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@auth/core@npm:^0.1.4":
|
||||
version: 0.1.4
|
||||
resolution: "@auth/core@npm:0.1.4"
|
||||
dependencies:
|
||||
"@panva/hkdf": 1.0.2
|
||||
cookie: 0.5.0
|
||||
jose: 4.11.1
|
||||
oauth4webapi: 2.0.5
|
||||
preact: 10.11.3
|
||||
preact-render-to-string: 5.2.3
|
||||
peerDependencies:
|
||||
nodemailer: 6.8.0
|
||||
peerDependenciesMeta:
|
||||
nodemailer:
|
||||
optional: true
|
||||
checksum: 64854404ea1883e0deb5535b34bed95cd43fc85094aeaf4f15a79e14045020eb944f844defe857edfc8528a0a024be89cbb2a3069dedef0e9217a74ca6c3eb79
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@aws-crypto/ie11-detection@npm:^3.0.0":
|
||||
version: 3.0.0
|
||||
resolution: "@aws-crypto/ie11-detection@npm:3.0.0"
|
||||
|
@ -3817,41 +3798,6 @@ __metadata:
|
|||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@calcom/auth@workspace:apps/auth":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@calcom/auth@workspace:apps/auth"
|
||||
dependencies:
|
||||
"@auth/core": ^0.1.4
|
||||
"@calcom/app-store": "*"
|
||||
"@calcom/app-store-cli": "*"
|
||||
"@calcom/config": "*"
|
||||
"@calcom/core": "*"
|
||||
"@calcom/dayjs": "*"
|
||||
"@calcom/embed-core": "workspace:*"
|
||||
"@calcom/embed-react": "workspace:*"
|
||||
"@calcom/embed-snippet": "workspace:*"
|
||||
"@calcom/features": "*"
|
||||
"@calcom/lib": "*"
|
||||
"@calcom/prisma": "*"
|
||||
"@calcom/trpc": "*"
|
||||
"@calcom/tsconfig": "*"
|
||||
"@calcom/types": "*"
|
||||
"@calcom/ui": "*"
|
||||
"@types/node": 16.9.1
|
||||
"@types/react": 18.0.26
|
||||
"@types/react-dom": ^18.0.9
|
||||
eslint: ^8.34.0
|
||||
eslint-config-next: ^13.2.1
|
||||
next: ^13.4.6
|
||||
next-auth: ^4.22.1
|
||||
postcss: ^8.4.18
|
||||
react: ^18.2.0
|
||||
react-dom: ^18.2.0
|
||||
tailwindcss: ^3.3.1
|
||||
typescript: ^4.9.4
|
||||
languageName: unknown
|
||||
linkType: soft
|
||||
|
||||
"@calcom/caldavcalendar@workspace:packages/app-store/caldavcalendar":
|
||||
version: 0.0.0-use.local
|
||||
resolution: "@calcom/caldavcalendar@workspace:packages/app-store/caldavcalendar"
|
||||
|
@ -4733,6 +4679,7 @@ __metadata:
|
|||
"@radix-ui/react-tooltip": ^1.0.0
|
||||
"@stripe/react-stripe-js": ^1.10.0
|
||||
"@stripe/stripe-js": ^1.35.0
|
||||
"@tanem/react-nprogress": ^5.0.44
|
||||
"@tanstack/react-query": ^4.3.9
|
||||
"@testing-library/react": ^13.3.0
|
||||
"@tremor/react": ^2.0.0
|
||||
|
@ -7575,13 +7522,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@panva/hkdf@npm:1.0.2":
|
||||
version: 1.0.2
|
||||
resolution: "@panva/hkdf@npm:1.0.2"
|
||||
checksum: 75183b4d5ea816ef516dcea70985c610683579a9e2ac540c2d59b9a3ed27eedaff830a43a1c43c1683556a457c92ac66e09109ee995ab173090e4042c4c4bb03
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@panva/hkdf@npm:^1.0.2":
|
||||
version: 1.0.4
|
||||
resolution: "@panva/hkdf@npm:1.0.4"
|
||||
|
@ -11122,6 +11062,19 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@tanem/react-nprogress@npm:^5.0.44":
|
||||
version: 5.0.44
|
||||
resolution: "@tanem/react-nprogress@npm:5.0.44"
|
||||
dependencies:
|
||||
"@babel/runtime": ^7.22.5
|
||||
hoist-non-react-statics: ^3.3.2
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||
react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0
|
||||
checksum: ada4f28cdad5aad378f5721561a6863f0b58fd0934a76fc9cd4b3c0a6961e359f267254362bbdbdaf89537358dba38465ef0b699154cf8d12c3a9e43a9980a4f
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@tanstack/query-core@npm:4.3.8":
|
||||
version: 4.3.8
|
||||
resolution: "@tanstack/query-core@npm:4.3.8"
|
||||
|
@ -23406,13 +23359,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"jose@npm:4.11.1":
|
||||
version: 4.11.1
|
||||
resolution: "jose@npm:4.11.1"
|
||||
checksum: cd15cba258d0fd20f6168631ce2e94fda8442df80e43c1033c523915cecdf390a1cc8efe0eab0c2d65935ca973d791c668aea80724d2aa9c2879d4e70f3081d7
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"jose@npm:4.12.0":
|
||||
version: 4.12.0
|
||||
resolution: "jose@npm:4.12.0"
|
||||
|
@ -26992,13 +26938,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"oauth4webapi@npm:2.0.5":
|
||||
version: 2.0.5
|
||||
resolution: "oauth4webapi@npm:2.0.5"
|
||||
checksum: 32d0cb7b1cca42d51dfb88075ca2d69fe33172a807e8ea50e317d17cab3bc80588ab8ebcb7eb4600c371a70af4674595b4b341daf6f3a655f1efa1ab715bb6c9
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"oauth@npm:^0.9.15":
|
||||
version: 0.9.15
|
||||
resolution: "oauth@npm:0.9.15"
|
||||
|
@ -28664,17 +28603,6 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"preact-render-to-string@npm:5.2.3":
|
||||
version: 5.2.3
|
||||
resolution: "preact-render-to-string@npm:5.2.3"
|
||||
dependencies:
|
||||
pretty-format: ^3.8.0
|
||||
peerDependencies:
|
||||
preact: ">=10"
|
||||
checksum: 6e46288d8956adde35b9fe3a21aecd9dea29751b40f0f155dea62f3896f27cb8614d457b32f48d33909d2da81135afcca6c55077520feacd7d15164d1371fb44
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"preact-render-to-string@npm:^5.1.19":
|
||||
version: 5.2.6
|
||||
resolution: "preact-render-to-string@npm:5.2.6"
|
||||
|
@ -28686,7 +28614,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"preact@npm:10.11.3, preact@npm:^10.6.3":
|
||||
"preact@npm:^10.6.3":
|
||||
version: 10.11.3
|
||||
resolution: "preact@npm:10.11.3"
|
||||
checksum: 9387115aa0581e8226309e6456e9856f17dfc0e3d3e63f774de80f3d462a882ba7c60914c05942cb51d51e23e120dcfe904b8d392d46f29ad15802941fe7a367
|
||||
|
|
Loading…
Reference in New Issue