From d56dd24a891a97683612ed731ea586855660117f Mon Sep 17 00:00:00 2001 From: Nicholas Chiang Date: Sun, 23 Jul 2023 20:47:15 -0600 Subject: [PATCH] feat: add `nprogress` page transition indicator This patch adds the nprogress page transition loading indicator. This is a temporary fix that should be addressed by simply making page transitions instantaneous. To do that, I will want to implement some type of caching or ISR strategy, or simply move back to using Fly.io on the edge (so my database is right next to my Node.js server). Closes: NC-642 --- app/app.css | 40 +++++++++++++++++++++++++++++++++++++ app/root.tsx | 15 +++++++++++++- app/routes/shows._index.tsx | 5 ++++- package.json | 2 ++ pnpm-lock.yaml | 14 +++++++++++++ 5 files changed, 74 insertions(+), 2 deletions(-) diff --git a/app/app.css b/app/app.css index 3a1ad5df..df458324 100644 --- a/app/app.css +++ b/app/app.css @@ -129,3 +129,43 @@ scrollbar-color: theme('colors.gray.800') theme('colors.gray.900'); } } + +/* Make clicks pass-through */ +#nprogress { + pointer-events: none; +} + +#nprogress .bar { + background: theme('colors.gray.900'); + + position: fixed; + z-index: 1031; + top: 0; + left: 0; + + width: 100%; + height: 2px; +} + +.dark #nprogress .bar { + background: theme('colors.gray.100'); +} + +/* Fancy blur effect */ +#nprogress .peg { + display: block; + position: absolute; + right: 0px; + width: 100px; + height: 100%; + box-shadow: 0 0 10px theme('colors.gray.900'), 0 0 5px theme('colors.gray.900'); + opacity: 1.0; + + -webkit-transform: rotate(3deg) translate(0px, -4px); + -ms-transform: rotate(3deg) translate(0px, -4px); + transform: rotate(3deg) translate(0px, -4px); +} + +.dark #nprogress .peg { + box-shadow: 0 0 10px theme('colors.gray.100'), 0 0 5px theme('colors.gray.100'); +} diff --git a/app/root.tsx b/app/root.tsx index 1627a132..84eba5ba 100644 --- a/app/root.tsx +++ b/app/root.tsx @@ -10,6 +10,7 @@ import { useRouteError, isRouteErrorResponse, useMatches, + useNavigation, type RouteMatch, } from '@remix-run/react' import { Analytics } from '@vercel/analytics/react' @@ -22,7 +23,8 @@ import { } from '@vercel/remix' import cn from 'classnames' import { LogIn, LogOut } from 'lucide-react' -import { Fragment, type ReactNode } from 'react' +import NProgress from 'nprogress' +import { Fragment, type ReactNode, useEffect } from 'react' import { ThemeSwitcher } from 'components/theme-switcher' import { buttonVariants } from 'components/ui/button' @@ -200,6 +202,17 @@ export type LoaderData = SerializeFrom function App({ data, children }: { data?: LoaderData; children: ReactNode }) { const [theme] = useTheme() + const navigation = useNavigation() + useEffect(() => { + // when the state is idle then we can complete the progress bar + if (navigation.state === 'idle') NProgress.done() + // and when it's something else it means it's either submitting a form or + // waiting for the loaders of the next location so we start it + else { + const timeoutId = setTimeout(() => NProgress.start(), 100) + return () => clearTimeout(timeoutId) + } + }, [navigation.state]) return ( diff --git a/app/routes/shows._index.tsx b/app/routes/shows._index.tsx index bfb09c43..65ce1a7e 100644 --- a/app/routes/shows._index.tsx +++ b/app/routes/shows._index.tsx @@ -7,7 +7,10 @@ import { prisma } from 'db.server' import { log } from 'log.server' export const meta: V2_MetaFunction = () => [ - { title: 'Fashion Shows: Fashion Week, Runway, Designer Collections | Nicholas Chiang' }, + { + title: + 'Fashion Shows: Fashion Week, Runway, Designer Collections | Nicholas Chiang', + }, ] export async function loader() { diff --git a/package.json b/package.json index 31466530..082bdade 100644 --- a/package.json +++ b/package.json @@ -77,6 +77,7 @@ "lucide-react": "^0.263.0", "morgan": "^1.10.0", "nanoid": "^4.0.2", + "nprogress": "^0.2.0", "pino": "^8.14.1", "pino-pretty": "^10.1.0", "prom-client": "^12.0.0", @@ -116,6 +117,7 @@ "@types/express-prometheus-middleware": "^1.2.1", "@types/morgan": "^1.9.4", "@types/node": "^18.16.20", + "@types/nprogress": "^0.2.0", "@types/progress": "^2.0.5", "@types/react": "^18.2.15", "@types/react-dom": "^18.2.7", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 65960fd4..b9fbb011 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -103,6 +103,9 @@ dependencies: nanoid: specifier: ^4.0.2 version: 4.0.2 + nprogress: + specifier: ^0.2.0 + version: 0.2.0 pino: specifier: ^8.14.1 version: 8.14.1 @@ -216,6 +219,9 @@ devDependencies: '@types/node': specifier: ^18.16.20 version: 18.16.20 + '@types/nprogress': + specifier: ^0.2.0 + version: 0.2.0 '@types/progress': specifier: ^2.0.5 version: 2.0.5 @@ -4687,6 +4693,10 @@ packages: resolution: {integrity: sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==} dev: true + /@types/nprogress@0.2.0: + resolution: {integrity: sha512-1cYJrqq9GezNFPsWTZpFut/d4CjpZqA0vhqDUPFWYKF1oIyBz5qnoYMzR+0C/T96t3ebLAC1SSnwrVOm5/j74A==} + dev: true + /@types/progress@2.0.5: resolution: {integrity: sha512-ZYYVc/kSMkhH9W/4dNK/sLNra3cnkfT2nJyOAIDY+C2u6w72wa0s1aXAezVtbTsnN8HID1uhXCrLwDE2ZXpplg==} dependencies: @@ -10925,6 +10935,10 @@ packages: - which - write-file-atomic + /nprogress@0.2.0: + resolution: {integrity: sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==} + dev: false + /nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} dependencies: