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: