mirror of
https://github.com/fosrl/pangolin.git
synced 2026-03-07 19:26:36 +00:00
💄 add toploader navigation
This commit is contained in:
34
package-lock.json
generated
34
package-lock.json
generated
@@ -72,10 +72,12 @@
|
|||||||
"next": "15.5.6",
|
"next": "15.5.6",
|
||||||
"next-intl": "^4.3.12",
|
"next-intl": "^4.3.12",
|
||||||
"next-themes": "0.4.6",
|
"next-themes": "0.4.6",
|
||||||
|
"nextjs-toploader": "^3.9.17",
|
||||||
"node-cache": "5.1.2",
|
"node-cache": "5.1.2",
|
||||||
"node-fetch": "3.3.2",
|
"node-fetch": "3.3.2",
|
||||||
"nodemailer": "7.0.9",
|
"nodemailer": "7.0.9",
|
||||||
"npm": "^11.6.2",
|
"npm": "^11.6.2",
|
||||||
|
"nprogress": "^0.2.0",
|
||||||
"oslo": "1.2.1",
|
"oslo": "1.2.1",
|
||||||
"pg": "^8.16.2",
|
"pg": "^8.16.2",
|
||||||
"posthog-node": "^5.9.5",
|
"posthog-node": "^5.9.5",
|
||||||
@@ -118,6 +120,7 @@
|
|||||||
"@types/jsonwebtoken": "^9.0.10",
|
"@types/jsonwebtoken": "^9.0.10",
|
||||||
"@types/node": "24.8.1",
|
"@types/node": "24.8.1",
|
||||||
"@types/nodemailer": "7.0.2",
|
"@types/nodemailer": "7.0.2",
|
||||||
|
"@types/nprogress": "^0.2.3",
|
||||||
"@types/pg": "8.15.5",
|
"@types/pg": "8.15.5",
|
||||||
"@types/react": "19.2.2",
|
"@types/react": "19.2.2",
|
||||||
"@types/react-dom": "19.2.2",
|
"@types/react-dom": "19.2.2",
|
||||||
@@ -8691,6 +8694,13 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@types/nprogress": {
|
||||||
|
"version": "0.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/nprogress/-/nprogress-0.2.3.tgz",
|
||||||
|
"integrity": "sha512-k7kRA033QNtC+gLc4VPlfnue58CM1iQLgn1IMAU8VPHGOj7oIHPp9UlhedEnD/Gl8evoCjwkZjlBORtZ3JByUA==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/@types/pg": {
|
"node_modules/@types/pg": {
|
||||||
"version": "8.15.5",
|
"version": "8.15.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.15.5.tgz",
|
"resolved": "https://registry.npmjs.org/@types/pg/-/pg-8.15.5.tgz",
|
||||||
@@ -15197,6 +15207,24 @@
|
|||||||
"node": "^10 || ^12 || >=14"
|
"node": "^10 || ^12 || >=14"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/nextjs-toploader": {
|
||||||
|
"version": "3.9.17",
|
||||||
|
"resolved": "https://registry.npmjs.org/nextjs-toploader/-/nextjs-toploader-3.9.17.tgz",
|
||||||
|
"integrity": "sha512-9OF0KSSLtoSAuNg2LZ3aTl4hR9mBDj5L9s9DZiFCbMlXehyICGjkIz5dVGzuATU2bheJZoBdFgq9w07AKSuQQw==",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"nprogress": "^0.2.0",
|
||||||
|
"prop-types": "^15.8.1"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://buymeacoffee.com/thesgj"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"next": ">= 6.0.0",
|
||||||
|
"react": ">= 16.0.0",
|
||||||
|
"react-dom": ">= 16.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/node-abi": {
|
"node_modules/node-abi": {
|
||||||
"version": "3.78.0",
|
"version": "3.78.0",
|
||||||
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.78.0.tgz",
|
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.78.0.tgz",
|
||||||
@@ -17727,6 +17755,12 @@
|
|||||||
"inBundle": true,
|
"inBundle": true,
|
||||||
"license": "ISC"
|
"license": "ISC"
|
||||||
},
|
},
|
||||||
|
"node_modules/nprogress": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==",
|
||||||
|
"license": "MIT"
|
||||||
|
},
|
||||||
"node_modules/nth-check": {
|
"node_modules/nth-check": {
|
||||||
"version": "2.1.1",
|
"version": "2.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
|
||||||
|
|||||||
@@ -95,10 +95,12 @@
|
|||||||
"next": "15.5.6",
|
"next": "15.5.6",
|
||||||
"next-intl": "^4.3.12",
|
"next-intl": "^4.3.12",
|
||||||
"next-themes": "0.4.6",
|
"next-themes": "0.4.6",
|
||||||
|
"nextjs-toploader": "^3.9.17",
|
||||||
"node-cache": "5.1.2",
|
"node-cache": "5.1.2",
|
||||||
"node-fetch": "3.3.2",
|
"node-fetch": "3.3.2",
|
||||||
"nodemailer": "7.0.9",
|
"nodemailer": "7.0.9",
|
||||||
"npm": "^11.6.2",
|
"npm": "^11.6.2",
|
||||||
|
"nprogress": "^0.2.0",
|
||||||
"oslo": "1.2.1",
|
"oslo": "1.2.1",
|
||||||
"pg": "^8.16.2",
|
"pg": "^8.16.2",
|
||||||
"posthog-node": "^5.9.5",
|
"posthog-node": "^5.9.5",
|
||||||
@@ -141,6 +143,7 @@
|
|||||||
"@types/jsonwebtoken": "^9.0.10",
|
"@types/jsonwebtoken": "^9.0.10",
|
||||||
"@types/node": "24.8.1",
|
"@types/node": "24.8.1",
|
||||||
"@types/nodemailer": "7.0.2",
|
"@types/nodemailer": "7.0.2",
|
||||||
|
"@types/nprogress": "^0.2.3",
|
||||||
"@types/pg": "8.15.5",
|
"@types/pg": "8.15.5",
|
||||||
"@types/react": "19.2.2",
|
"@types/react": "19.2.2",
|
||||||
"@types/react-dom": "19.2.2",
|
"@types/react-dom": "19.2.2",
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
.dark {
|
||||||
--background: oklch(0.20 0.006 285.885);
|
--background: oklch(0.2 0.006 285.885);
|
||||||
--foreground: oklch(0.985 0 0);
|
--foreground: oklch(0.985 0 0);
|
||||||
--card: oklch(0.21 0.006 285.885);
|
--card: oklch(0.21 0.006 285.885);
|
||||||
--card-foreground: oklch(0.985 0 0);
|
--card-foreground: oklch(0.985 0 0);
|
||||||
@@ -140,3 +140,7 @@ p {
|
|||||||
word-break: keep-all;
|
word-break: keep-all;
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#nprogress .bar {
|
||||||
|
background: var(--color-primary) !important;
|
||||||
|
}
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import { NextIntlClientProvider } from "next-intl";
|
|||||||
import { getLocale } from "next-intl/server";
|
import { getLocale } from "next-intl/server";
|
||||||
import { Toaster } from "@app/components/ui/toaster";
|
import { Toaster } from "@app/components/ui/toaster";
|
||||||
import { build } from "@server/build";
|
import { build } from "@server/build";
|
||||||
|
import { TopLoader } from "@app/components/Toploader";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: `Dashboard - ${process.env.BRANDING_APP_NAME || "Pangolin"}`,
|
title: `Dashboard - ${process.env.BRANDING_APP_NAME || "Pangolin"}`,
|
||||||
@@ -62,9 +63,9 @@ export default async function RootLayout({
|
|||||||
if (build === "enterprise") {
|
if (build === "enterprise") {
|
||||||
const licenseStatusRes = await cache(
|
const licenseStatusRes = await cache(
|
||||||
async () =>
|
async () =>
|
||||||
await priv.get<AxiosResponse<GetLicenseStatusResponse>>(
|
await priv.get<AxiosResponse<GetLicenseStatusResponse>>(
|
||||||
"/license/status"
|
"/license/status"
|
||||||
)
|
)
|
||||||
)();
|
)();
|
||||||
licenseStatus = licenseStatusRes.data.data;
|
licenseStatus = licenseStatusRes.data.data;
|
||||||
} else if (build === "saas") {
|
} else if (build === "saas") {
|
||||||
@@ -84,6 +85,7 @@ export default async function RootLayout({
|
|||||||
return (
|
return (
|
||||||
<html suppressHydrationWarning lang={locale}>
|
<html suppressHydrationWarning lang={locale}>
|
||||||
<body className={`${font.className} h-screen overflow-hidden`}>
|
<body className={`${font.className} h-screen overflow-hidden`}>
|
||||||
|
<TopLoader />
|
||||||
<NextIntlClientProvider>
|
<NextIntlClientProvider>
|
||||||
<ThemeProvider
|
<ThemeProvider
|
||||||
attribute="class"
|
attribute="class"
|
||||||
|
|||||||
41
src/components/Toploader.tsx
Normal file
41
src/components/Toploader.tsx
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
"use client";
|
||||||
|
import * as React from "react";
|
||||||
|
import * as NProgress from "nprogress";
|
||||||
|
import NextTopLoader from "nextjs-toploader";
|
||||||
|
import { usePathname, useRouter, useSearchParams } from "next/navigation";
|
||||||
|
|
||||||
|
export function TopLoader() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<NextTopLoader showSpinner={false} />
|
||||||
|
<FinishingLoader />
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function FinishingLoader() {
|
||||||
|
const pathname = usePathname();
|
||||||
|
const router = useRouter();
|
||||||
|
const searchParams = useSearchParams();
|
||||||
|
React.useEffect(() => {
|
||||||
|
NProgress.done();
|
||||||
|
}, [pathname, router, searchParams]);
|
||||||
|
React.useEffect(() => {
|
||||||
|
const linkClickListener = (ev: MouseEvent) => {
|
||||||
|
const element = ev.target as HTMLElement;
|
||||||
|
const closestlink = element.closest("a");
|
||||||
|
const isOpenToNewTabClick =
|
||||||
|
ev.ctrlKey ||
|
||||||
|
ev.shiftKey ||
|
||||||
|
ev.metaKey || // apple
|
||||||
|
(ev.button && ev.button == 1); // middle click, >IE9 + everyone else
|
||||||
|
|
||||||
|
if (closestlink && isOpenToNewTabClick) {
|
||||||
|
NProgress.done();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
window.addEventListener("click", linkClickListener);
|
||||||
|
return () => window.removeEventListener("click", linkClickListener);
|
||||||
|
}, []);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user