Skip to content

Commit

Permalink
style: πŸ’„ Addded Progress Indicator while navigating pages
Browse files Browse the repository at this point in the history
Progress Indicator will show on top of page, when navigate to between
pages

βœ… Closes: #163
  • Loading branch information
growupanand committed Feb 1, 2024
1 parent 37e3a17 commit 4876b35
Show file tree
Hide file tree
Showing 10 changed files with 162 additions and 30 deletions.
13 changes: 13 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@
"jotai": "^2.6.1",
"lucide-react": "^0.292.0",
"next": "14.0.3",
"nprogress": "^0.2.0",
"openai": "^4.24.2",
"openai-edge": "^1.2.2",
"react": "^18",
Expand All @@ -75,6 +76,7 @@
"@release-it/conventional-changelog": "^8.0.1",
"@swc-jotai/react-refresh": "^0.1.0",
"@types/node": "^20",
"@types/nprogress": "^0.2.3",
"@types/react": "^18",
"@types/react-dom": "^18",
"@typescript-eslint/eslint-plugin": "^6.18.0",
Expand Down
1 change: 1 addition & 0 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Metadata } from "next";

import "./globals.css";
import "nprogress/nprogress.css";

import { ClerkProvider } from "@clerk/nextjs";

Expand Down
7 changes: 3 additions & 4 deletions src/components/common/brandName.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import Link from "next/link";

import { montserrat } from "@/app/fonts";
import { LinkN } from "@/components/linkN";
import { brandName } from "@/lib/constants";
import { cn } from "@/lib/utils";

Expand All @@ -10,7 +9,7 @@ type Props = {

export default function BrandName({ className = "" }: Props) {
return (
<Link href="/">
<LinkN href="/">
<span
className={cn(
"font-semibold text-foreground",
Expand All @@ -20,6 +19,6 @@ export default function BrandName({ className = "" }: Props) {
>
{brandName}
</span>
</Link>
</LinkN>
);
}
26 changes: 14 additions & 12 deletions src/components/formEditorPage/formEditorPageHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
"use client";

import Link from "next/link";
import { UserButton } from "@clerk/nextjs";
import { Form, Workspace } from "@prisma/client";
import { ChevronLeft, ChevronRight, Home } from "lucide-react";

import { montserrat } from "@/app/fonts";
import { LinkN } from "@/components/linkN";
import { cn } from "@/lib/utils";
import { Button } from "../ui/button";
import { Skeleton } from "../ui/skeleton";
Expand All @@ -28,30 +28,32 @@ function FormEditorPageHeader({ form, workspace }: Props) {
)}
>
<Button size="sm" variant="link" asChild>
<Link href={"/dashboard"}>
<LinkN href={"/dashboard"}>
<Home size={20} />
</Link>
</LinkN>
</Button>
<ChevronRight size={20} />
<Button size="sm" variant="link" asChild>
<Link href={"/dashboard"}>Dashboard</Link>
</Button>
<LinkN href={"/dashboard"}>
<Button size="sm" variant="link">
Dashboard
</Button>
</LinkN>
<ChevronRight size={20} />
<Button size="sm" variant="link" asChild>
<Link href={`/workspaces/${form.workspaceId}`}>
<LinkN href={`/workspaces/${form.workspaceId}`}>
<Button size="sm" variant="link">
{workspace.name}
</Link>
</Button>
</Button>
</LinkN>
<ChevronRight size={20} />
<FormNameInput form={form} className="w-full text-xl font-medium" />
</div>
<div className="lg:hidden">
<Link href={`/workspaces/${form.workspaceId}`}>
<LinkN href={`/workspaces/${form.workspaceId}`}>
<Button size="sm" variant="link" className="px-0 text-sm">
<ChevronLeft className="mr-2" size={20} />
Back
</Button>
</Link>
</LinkN>
</div>
<div className="overflow-hidden lg:hidden">
<FormNameInput form={form} className="text-xl font-medium" />
Expand Down
10 changes: 5 additions & 5 deletions src/components/landingPage/header.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Link from "next/link";
import { auth } from "@clerk/nextjs";
import { LayoutDashboard } from "lucide-react";

import { LinkN } from "@/components/linkN";
import BrandName from "../common/brandName";
import { Button } from "../ui/button";

Expand All @@ -14,17 +14,17 @@ export function Header() {
<BrandName className="text-xl lg:text-2xl" />
<nav className="flex items-center gap-3">
{userId ? (
<Link href="/dashboard">
<LinkN href="/dashboard">
<Button variant="secondary">
<LayoutDashboard className="mr-2" size={20} /> Go to Dashboard
</Button>
</Link>
</LinkN>
) : (
<Link href="/auth/sign-in" rel="noopener noreferrer nofollow">
<LinkN href="/auth/sign-in" rel="noopener noreferrer nofollow">
<Button variant="secondary" className="rounded-full">
Sign In
</Button>
</Link>
</LinkN>
)}
</nav>
</div>
Expand Down
9 changes: 5 additions & 4 deletions src/components/landingPage/hero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Link from "next/link";
import { ChevronRight } from "lucide-react";

import { montserrat } from "@/app/fonts";
import { LinkN } from "@/components/linkN";
import { getFrontendBaseUrl } from "@/lib/url";
import { cn } from "@/lib/utils";
import { Badge } from "../ui/badge";
Expand Down Expand Up @@ -55,19 +56,19 @@ export function Hero() {
className={cn("rounded-full lg:text-lg", montserrat.className)}
asChild
>
<Link href="/auth/register" rel="noreferrer nofollow noopener">
<LinkN href="/auth/register" rel="noreferrer nofollow noopener">
Get started
</Link>
</LinkN>
</Button>
<Button
size="lg"
variant="outline"
className={cn("rounded-full lg:text-lg", montserrat.className)}
asChild
>
<Link href={demoFormLink} target="_blank">
<LinkN href={demoFormLink} target="_blank">
Try demo form
</Link>
</LinkN>
</Button>
</div>
</section>
Expand Down
6 changes: 3 additions & 3 deletions src/components/landingPage/pricing.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import Link from "next/link";
import { auth } from "@clerk/nextjs";
import { CheckCircle } from "lucide-react";

import { montserrat } from "@/app/fonts";
import { LinkN } from "@/components/linkN";
import { freePlan } from "@/lib/config/pricing";
import { Plan } from "@/lib/types/pricing";
import { cn } from "@/lib/utils";
Expand Down Expand Up @@ -87,9 +87,9 @@ const PlanCard = ({ plan }: { plan: Plan }) => {
className={cn("w-full rounded-full font-bold", montserrat.className)}
asChild
>
<Link href={isLoggedin ? "/dashboard" : "/auth/register"}>
<LinkN href={isLoggedin ? "/dashboard" : "/auth/register"}>
Sign up now
</Link>
</LinkN>
</Button>
</CardFooter>
</Card>
Expand Down
113 changes: 113 additions & 0 deletions src/components/linkN.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
"use client";

import { PropsWithChildren, useEffect } from "react";
import Link from "next/link";
import NProgress from "nprogress";

import { cn } from "@/lib/utils";

/**
* Currently, In Next.js app router there is no way to listen to route change events,
* so i found only this solution here - https://github.com/vercel/next.js/discussions/41934#discussioncomment-7195052
*
*/

// TODO: Use router events when it will be available in Next.js app router

/**
* Do not use this where link will remain on the same page, It will work only where link component will dismount
* @param param0
* @returns
*/
export const LinkN: React.FC<
PropsWithChildren<{
href: string;
target?: string;
rel?: string;
className?: string;
}>
> = ({ href, children, className, target, rel }) => {
NProgress.configure({ showSpinner: false });

useEffect(() => {
return () => {
NProgress.done();
};
}, []);

const handleClick = (e: React.MouseEvent<HTMLAnchorElement>) => {
if (shouldStartAnimation(e)) {
NProgress.start();
}
};

const handleKeyDown = (e: React.KeyboardEvent<HTMLAnchorElement>) => {
if (shouldStartAnimation(e)) {
NProgress.start();
}
};

const shouldStartAnimation = (
e:
| React.MouseEvent<HTMLAnchorElement>
| React.KeyboardEvent<HTMLAnchorElement>,
): boolean => {
// Check if it's a left mouse click without any keyboard modifiers
if (
(e as React.MouseEvent<HTMLAnchorElement>).button === 0 &&
!(e as React.MouseEvent<HTMLAnchorElement>).ctrlKey &&
!(e as React.MouseEvent<HTMLAnchorElement>).shiftKey &&
!(e as React.MouseEvent<HTMLAnchorElement>).metaKey
) {
// Get the current pathname from window.location
const currentPathname = window.location.pathname;

// Check if the link's href is the same as the current pathname
if (href === currentPathname) {
return false; // Don't start the animation for same route links
}

// Check if link will open new window or tab
if (target && target !== "_self") {
return false;
}

return true;
}

// Check for middle mouse button click
if ((e as React.MouseEvent<HTMLAnchorElement>).button === 1) {
return false;
}

// Check for right mouse button click
if ((e as React.MouseEvent<HTMLAnchorElement>).button === 2) {
return false;
}

// Check if it's an accessibility event (e.g., screen reader activation)
if (
e.type === "click" &&
(e as React.MouseEvent<HTMLAnchorElement>).detail === 0
) {
return true;
}

return false;
};

return (
<Link href={href} legacyBehavior>
<a
onClick={handleClick}
onKeyDown={handleKeyDown}
tabIndex={0}
className={cn(className)} // Ensure the link is keyboard focusable
target={target}
rel={rel}
>
{children}
</a>
</Link>
);
};
5 changes: 3 additions & 2 deletions src/components/mainPage/workspace/formListItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
Trash,
} from "lucide-react";

import { LinkN } from "@/components/linkN";
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
Expand Down Expand Up @@ -79,14 +80,14 @@ export function FormListItem({ form, onDeleted }: Readonly<Props>) {
return (
<div className="flex items-center justify-between py-1 transition-all hover:bg-gray-50 hover:ps-3">
<div className="grow">
<Link href={`/forms/${form.id}`}>
<LinkN href={`/forms/${form.id}`}>
<Button
variant="link"
className="w-full justify-start ps-0 font-normal hover:no-underline "
>
{form.name}
</Button>
</Link>
</LinkN>
</div>

<div className="flex items-center gap-3">
Expand Down

0 comments on commit 4876b35

Please sign in to comment.