From e06c1a9fbc4ce11834104bfc5219b90d6c575188 Mon Sep 17 00:00:00 2001 From: Trugamr Date: Sat, 13 Jan 2024 21:53:31 +0530 Subject: [PATCH] feat: add global navigation progress --- app/components/global-navigation-progress.tsx | 39 +++++++++++++++++++ app/globals.css | 10 +++++ app/root.tsx | 6 ++- package.json | 3 ++ pnpm-lock.yaml | 25 ++++++++++++ 5 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 app/components/global-navigation-progress.tsx diff --git a/app/components/global-navigation-progress.tsx b/app/components/global-navigation-progress.tsx new file mode 100644 index 0000000..16c297e --- /dev/null +++ b/app/components/global-navigation-progress.tsx @@ -0,0 +1,39 @@ +import { useFetchers, useNavigation } from '@remix-run/react' +import nProgress from 'nprogress' +import { useEffect, useMemo } from 'react' +import { useSpinDelay } from 'spin-delay' + +export function GlobalNavigationProgress() { + const navigation = useNavigation() + const fetchers = useFetchers() + + const loading = useMemo(() => { + if (navigation.state === 'idle' && fetchers.every(f => f.state === 'idle')) { + return false + } + return true + }, [navigation.state, fetchers]) + + const delayedLoading = useSpinDelay(loading, { + delay: 150, + minDuration: 200, + }) + + useEffect(() => { + nProgress.configure({ showSpinner: false }) + + return () => { + nProgress.remove() + } + }, []) + + useEffect(() => { + if (delayedLoading) { + nProgress.start() + } else { + nProgress.done() + } + }, [delayedLoading]) + + return null +} diff --git a/app/globals.css b/app/globals.css index 41dfa1b..25c62ea 100644 --- a/app/globals.css +++ b/app/globals.css @@ -76,3 +76,13 @@ @apply bg-background text-foreground; } } + +/* Change NProgress color, height */ +#nprogress .bar { + @apply h-1 bg-primary; +} + +/* Disable NProgress blur effect */ +#nprogress .peg { + @apply hidden; +} diff --git a/app/root.tsx b/app/root.tsx index 5bd2c2d..0296603 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -10,9 +10,12 @@ import { } from '@remix-run/react' import { PackageIcon, RocketIcon } from 'lucide-react' import React from 'react' -import '~/globals.css' import { buttonVariants } from './components/ui/button' import { MetaFunction } from '@remix-run/node' +import { GlobalNavigationProgress } from './components/global-navigation-progress' + +import 'nprogress/nprogress.css' +import '~/globals.css' export const meta: MetaFunction = () => { return [{ title: 'dabba' }] @@ -55,6 +58,7 @@ const links = [ export default function App() { return ( +
diff --git a/package.json b/package.json index 2adebbc..d9911d9 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "remix-utils": "^7.5.0", + "spin-delay": "^1.2.0", "tailwind-merge": "^2.2.0", "tailwindcss-animate": "^1.0.7", "ts-pattern": "^5.0.6", @@ -32,6 +33,7 @@ }, "devDependencies": { "@remix-run/dev": "^2.4.1", + "@types/nprogress": "^0.2.3", "@types/react": "^18.2.20", "@types/react-dom": "^18.2.7", "@typescript-eslint/eslint-plugin": "^6.7.4", @@ -43,6 +45,7 @@ "eslint-plugin-jsx-a11y": "^6.7.1", "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", + "nprogress": "^0.2.0", "postcss": "^8.4.33", "prettier": "^3.1.1", "prettier-plugin-tailwindcss": "^0.5.11", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 809355f..7e15959 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -44,6 +44,9 @@ dependencies: remix-utils: specifier: ^7.5.0 version: 7.5.0(@remix-run/node@2.4.1)(@remix-run/react@2.4.1)(react@18.2.0)(zod@3.22.4) + spin-delay: + specifier: ^1.2.0 + version: 1.2.0(react@18.2.0) tailwind-merge: specifier: ^2.2.0 version: 2.2.0 @@ -61,6 +64,9 @@ devDependencies: '@remix-run/dev': specifier: ^2.4.1 version: 2.4.1(@remix-run/serve@2.4.1)(typescript@5.3.3)(vite@5.0.11) + '@types/nprogress': + specifier: ^0.2.3 + version: 0.2.3 '@types/react': specifier: ^18.2.20 version: 18.2.47 @@ -94,6 +100,9 @@ devDependencies: eslint-plugin-react-hooks: specifier: ^4.6.0 version: 4.6.0(eslint@8.56.0) + nprogress: + specifier: ^0.2.0 + version: 0.2.0 postcss: specifier: ^8.4.33 version: 8.4.33 @@ -1669,6 +1678,10 @@ packages: undici-types: 5.26.5 dev: true + /@types/nprogress@0.2.3: + resolution: {integrity: sha512-k7kRA033QNtC+gLc4VPlfnue58CM1iQLgn1IMAU8VPHGOj7oIHPp9UlhedEnD/Gl8evoCjwkZjlBORtZ3JByUA==} + dev: true + /@types/prop-types@15.7.11: resolution: {integrity: sha512-ga8y9v9uyeiLdpKddhxYQkxNDrfvuPrlFb0N1qnZZByvcElJaXthF1UhvCh9TLWJBEHeNtdnbysW7Y6Uq8CVng==} @@ -4860,6 +4873,10 @@ packages: path-key: 4.0.0 dev: false + /nprogress@0.2.0: + resolution: {integrity: sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==} + dev: true + /object-assign@4.1.1: resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} engines: {node: '>=0.10.0'} @@ -5907,6 +5924,14 @@ packages: resolution: {integrity: sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==} dev: true + /spin-delay@1.2.0(react@18.2.0): + resolution: {integrity: sha512-PkZl5FHWOMrwQgoWejG1hBkIlVx4KbdL/37RPr5/pGq5+NWcGx7NNDukFct2yr8yRZuvwEompNR/in9nWj4sTw==} + peerDependencies: + react: '>=17.0.1' + dependencies: + react: 18.2.0 + dev: false + /ssri@10.0.5: resolution: {integrity: sha512-bSf16tAFkGeRlUNDjXu8FzaMQt6g2HZJrun7mtMbIPOddxt3GLMSz5VWUWcqTJUPfLEaDIepGxv+bYQW49596A==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}