From 5971db19ab12e79593d8fea755b8830788fd0128 Mon Sep 17 00:00:00 2001 From: 10daer Date: Sun, 4 May 2025 15:30:41 +0100 Subject: [PATCH 1/3] initial commit --- public/LoginSteps/LoginStep1.svg | 9 + public/LoginSteps/LoginStep2.svg | 64 ++++++ public/LoginSteps/LoginStep3.svg | 69 ++++++ public/LoginSteps/LoginStep4.svg | 69 ++++++ public/LoginSteps/LoginStep5.svg | 60 ++++++ public/LoginSteps/LoginStep6.svg | 46 ++++ public/SignupSteps/SignupStep1.svg | 37 ++++ public/SignupSteps/SignupStep2.svg | 71 +++++++ public/SignupSteps/SignupStep3.svg | 45 ++++ public/SignupSteps/SignupStep4.svg | 57 +++++ public/SignupSteps/SignupStep5.svg | 58 +++++ public/SignupSteps/SignupStep6.svg | 43 ++++ public/logo.svg | 9 + src/app/globals.css | 201 +++++++++++++++--- .../_components/AnimatedContent.tsx | 21 ++ .../_components/AnimatedImage.tsx | 18 ++ src/app/how-it-works/_components/Button.tsx | 15 ++ .../how-it-works/_components/FaqSection.tsx | 76 +++++++ src/app/how-it-works/_components/Footer.tsx | 68 ++++++ .../how-it-works/_components/LoginStep.tsx | 79 +++++++ src/app/how-it-works/_components/Logo.tsx | 14 ++ src/app/how-it-works/_components/NavLink.tsx | 12 ++ src/app/how-it-works/_components/NavMenu.tsx | 54 +++++ .../_components/NavMenuButton.tsx | 26 +++ .../how-it-works/_components/NavSearchBar.tsx | 44 ++++ src/app/how-it-works/_components/Navbar.tsx | 42 ++++ .../_components/SelectChoiceButton.tsx | 13 ++ .../how-it-works/_components/SignupStep.tsx | 84 ++++++++ .../_components/StepByStepSection.tsx | 36 ++++ src/app/how-it-works/_components/types.ts | 34 +++ src/app/how-it-works/page.tsx | 30 +++ 31 files changed, 1477 insertions(+), 27 deletions(-) create mode 100644 public/LoginSteps/LoginStep1.svg create mode 100644 public/LoginSteps/LoginStep2.svg create mode 100644 public/LoginSteps/LoginStep3.svg create mode 100644 public/LoginSteps/LoginStep4.svg create mode 100644 public/LoginSteps/LoginStep5.svg create mode 100644 public/LoginSteps/LoginStep6.svg create mode 100644 public/SignupSteps/SignupStep1.svg create mode 100644 public/SignupSteps/SignupStep2.svg create mode 100644 public/SignupSteps/SignupStep3.svg create mode 100644 public/SignupSteps/SignupStep4.svg create mode 100644 public/SignupSteps/SignupStep5.svg create mode 100644 public/SignupSteps/SignupStep6.svg create mode 100644 public/logo.svg create mode 100644 src/app/how-it-works/_components/AnimatedContent.tsx create mode 100644 src/app/how-it-works/_components/AnimatedImage.tsx create mode 100644 src/app/how-it-works/_components/Button.tsx create mode 100644 src/app/how-it-works/_components/FaqSection.tsx create mode 100644 src/app/how-it-works/_components/Footer.tsx create mode 100644 src/app/how-it-works/_components/LoginStep.tsx create mode 100644 src/app/how-it-works/_components/Logo.tsx create mode 100644 src/app/how-it-works/_components/NavLink.tsx create mode 100644 src/app/how-it-works/_components/NavMenu.tsx create mode 100644 src/app/how-it-works/_components/NavMenuButton.tsx create mode 100644 src/app/how-it-works/_components/NavSearchBar.tsx create mode 100644 src/app/how-it-works/_components/Navbar.tsx create mode 100644 src/app/how-it-works/_components/SelectChoiceButton.tsx create mode 100644 src/app/how-it-works/_components/SignupStep.tsx create mode 100644 src/app/how-it-works/_components/StepByStepSection.tsx create mode 100644 src/app/how-it-works/_components/types.ts create mode 100644 src/app/how-it-works/page.tsx diff --git a/public/LoginSteps/LoginStep1.svg b/public/LoginSteps/LoginStep1.svg new file mode 100644 index 0000000..de87ea8 --- /dev/null +++ b/public/LoginSteps/LoginStep1.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/public/LoginSteps/LoginStep2.svg b/public/LoginSteps/LoginStep2.svg new file mode 100644 index 0000000..86889f5 --- /dev/null +++ b/public/LoginSteps/LoginStep2.svg @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/LoginSteps/LoginStep3.svg b/public/LoginSteps/LoginStep3.svg new file mode 100644 index 0000000..61137fc --- /dev/null +++ b/public/LoginSteps/LoginStep3.svg @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/LoginSteps/LoginStep4.svg b/public/LoginSteps/LoginStep4.svg new file mode 100644 index 0000000..e7768f8 --- /dev/null +++ b/public/LoginSteps/LoginStep4.svg @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/LoginSteps/LoginStep5.svg b/public/LoginSteps/LoginStep5.svg new file mode 100644 index 0000000..cb1d5e2 --- /dev/null +++ b/public/LoginSteps/LoginStep5.svg @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/LoginSteps/LoginStep6.svg b/public/LoginSteps/LoginStep6.svg new file mode 100644 index 0000000..c28ce3b --- /dev/null +++ b/public/LoginSteps/LoginStep6.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/SignupSteps/SignupStep1.svg b/public/SignupSteps/SignupStep1.svg new file mode 100644 index 0000000..9f106ec --- /dev/null +++ b/public/SignupSteps/SignupStep1.svg @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/SignupSteps/SignupStep2.svg b/public/SignupSteps/SignupStep2.svg new file mode 100644 index 0000000..abd00b4 --- /dev/null +++ b/public/SignupSteps/SignupStep2.svg @@ -0,0 +1,71 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/SignupSteps/SignupStep3.svg b/public/SignupSteps/SignupStep3.svg new file mode 100644 index 0000000..fd3b720 --- /dev/null +++ b/public/SignupSteps/SignupStep3.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/SignupSteps/SignupStep4.svg b/public/SignupSteps/SignupStep4.svg new file mode 100644 index 0000000..5b2548c --- /dev/null +++ b/public/SignupSteps/SignupStep4.svg @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/SignupSteps/SignupStep5.svg b/public/SignupSteps/SignupStep5.svg new file mode 100644 index 0000000..c3f05aa --- /dev/null +++ b/public/SignupSteps/SignupStep5.svg @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/SignupSteps/SignupStep6.svg b/public/SignupSteps/SignupStep6.svg new file mode 100644 index 0000000..bf7b657 --- /dev/null +++ b/public/SignupSteps/SignupStep6.svg @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/logo.svg b/public/logo.svg new file mode 100644 index 0000000..624ad8e --- /dev/null +++ b/public/logo.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/app/globals.css b/src/app/globals.css index 2fdbe6b..70a6b9c 100644 --- a/src/app/globals.css +++ b/src/app/globals.css @@ -3,10 +3,54 @@ @custom-variant dark (&:is(.dark *)); @theme inline { + /* Background and Foreground */ + --color-background: #ffffff; /* White */ + --color-foreground-primary: #0353f0; /* Light Blue */ + --color-foreground-secondary: #000b21; /* Dark Blue */ + --color-foreground-neutral: #121212; /* Very Dark Blue */ + + /* Primary Colors */ + --color-primary-50: #edf7ff; + --color-primary-100: #d6ecff; + --color-primary-200: #b6e0ff; + --color-primary-300: #84cdff; + --color-primary-400: #44b1ff; + --color-primary-500: #218bff; + --color-primary-600: #096cff; + --color-primary-700: #0355f0; + --color-primary-800: #0443c3; + --color-primary-900: #0f3d99; + --color-primary-950: #0f265c; + + /* Secondary Colors */ + --color-secondary-50: #e9f7ff; + --color-secondary-100: #ceedff; + --color-secondary-200: #a7e1ff; + --color-secondary-300: #6bd2ff; + --color-secondary-400: #26b6ff; + --color-secondary-500: #008bff; + --color-secondary-600: #0061ff; + --color-secondary-700: #0046ff; + --color-secondary-800: #003be6; + --color-secondary-900: #0033b3; + --color-secondary-950: #000821; + + /* Neutral Colors */ + --color-neutral-50: #f6f6f6; + --color-neutral-100: #e7e7e7; + --color-neutral-200: #d1d1d1; + --color-neutral-300: #b0b0b0; + --color-neutral-400: #888888; + --color-neutral-500: #6d6d6d; + --color-neutral-600: #5d5d5d; + --color-neutral-700: #4f4f4f; + --color-neutral-800: #454545; + --color-neutral-900: #3d3d3d; + --color-neutral-950: #121212; + + /* Additional colors */ --color-background: var(--background); --color-foreground: var(--foreground); - --font-sans: var(--font-geist-sans); - --font-mono: var(--font-geist-mono); --color-sidebar-ring: var(--sidebar-ring); --color-sidebar-border: var(--sidebar-border); --color-sidebar-accent-foreground: var(--sidebar-accent-foreground); @@ -36,10 +80,103 @@ --color-popover: var(--popover); --color-card-foreground: var(--card-foreground); --color-card: var(--card); + + /* Font Family */ + --font-sans: Inter, sans-serif; + --font-sans: var(--font-geist-sans); + --font-mono: var(--font-geist-mono); + + /* DIsplay TextSizes */ + --text-display-large: 57px; + --text-display-large--line-height: 64px; + --text-display-large--letter-spacing: -0.25px; + --text-display-medium: 45px; + --text-display-medium--line-height: 52px; + --text-display-medium--letter-spacing: 0px; + --text-display-small: 32px; + --text-display-small--line-height: 44px; + --text-display-small--letter-spacing: 0px; + + /* Heading TextSizes */ + --text-headline-xl-large: 44px; + --text-headline-xl-large--line-height: 100%; + --text-headline-xl-large--letter-spacing: 0px; + --text-headline-x-large: 40px; + --text-headline-x-large--line-height: 100%; + --text-headline-x-large--letter-spacing: 0px; + --text-headline-large: 32px; + --text-headline-large--line-height: 40px; + --text-headline-large--letter-spacing: 0px; + --text-headline-medium: 28px; + --text-headline-medium--line-height: 36px; + --text-headline-medium--letter-spacing: 0px; + --text-headline-small: 24px; + --text-headline-small--line-height: 32px; + --text-headline-small--letter-spacing: 0px; + + /* Title TextSizes */ + --text-title-large: 22px; + --text-title-large--line-height: 28px; + --text-title-large--letter-spacing: 0px; + --text-title-medium: 16px; + --text-title-medium--line-height: 20px; + --text-title-medium--letter-spacing: 0.15px; + --text-title-small: 14px; + --text-title-small--line-height: 20px; + --text-title-small--letter-spacing: 0.1px; + + /* Logo TextSizes */ + --text-logo: 20.5px; + --text-logo--line-height: 26px; + --text-logo--letter-spacing: 0px; + + /* Body TextSizes */ + --text-body-large: 16px; + --text-body-large--line-height: 24px; + --text-body-large--letter-spacing: 0px; + --text-body-medium: 14px; + --text-body-medium--line-height: 18px; + --text-body-medium--letter-spacing: 0.25px; + --text-body-small: 12px; + --text-body-small--line-height: 16px; + --text-body-small--letter-spacing: 0.4px; + --text-body-18px-large: 18px; + --text-body-18px-large--line-height: 26px; + --text-body-18px-large--letter-spacing: 0px; + + /* Label TextSizes */ + --text-label-large: 14px; + --text-label-large--line-height: 100%; + --text-label-large--letter-spacing: 0px; + --text-label-medium: 14px; + --text-label-medium--line-height: 20px; + --text-label-medium--letter-spacing: 0.1px; + --text-label-small: 11px; + --text-label-small--line-height: 16px; + --text-label-small--letter-spacing: 0.5px; + --text-label-xs: 9px; + --text-label-xs--line-height: 12px; + --text-label-xs--letter-spacing: 0.8px; + + /* Font Weights */ + --font-weight-light: 400; + --font-weight-medium: 500; + --font-weight-bold: 700; + + /* Radius */ + --radius-x-large: 28px; + --radius-large: 16px; + --radius-base: 12px; + --radius-small: 8px; + --radius-x-small: 4px; --radius-sm: calc(var(--radius) - 4px); --radius-md: calc(var(--radius) - 2px); --radius-lg: var(--radius); --radius-xl: calc(var(--radius) + 4px); + + /* Shadow */ + --shadow-large: 0px 20px 16px 0px #00000014; + --shadow-base: 0px 12px 16px 0px #0000000a; } :root { @@ -75,6 +212,10 @@ --sidebar-accent-foreground: oklch(0.205 0 0); --sidebar-border: oklch(0.922 0 0); --sidebar-ring: oklch(0.708 0 0); + + * { + /* outline: 1px solid black; */ + } } .dark { @@ -111,13 +252,32 @@ --sidebar-ring: oklch(0.556 0 0); } -@layer base { - * { - @apply border-border outline-ring/50; - } - body { - @apply bg-background text-foreground; - } +* { + @apply border-border outline-ring/50; +} + +body { + @apply bg-background text-foreground; +} + +html::-webkit-scrollbar { + display: none; + width: 0px; +} + +html { + scrollbar-width: none; +} + +html { + -ms-overflow-style: none; +} + +html { + overflow-y: scroll; + overflow-x: hidden; + scroll-behavior: smooth; + -webkit-overflow-scrolling: touch; } .splide__pagination { @@ -138,24 +298,6 @@ background: #b0b0b0 !important; } - - - - - - - - - - - - - - - - - - @media (max-width: 1024px) { .splide__pagination__page { width: 20px !important; @@ -173,3 +315,8 @@ gap: 10px; } } + +button, +a { + cursor: pointer; +} diff --git a/src/app/how-it-works/_components/AnimatedContent.tsx b/src/app/how-it-works/_components/AnimatedContent.tsx new file mode 100644 index 0000000..0ac56a7 --- /dev/null +++ b/src/app/how-it-works/_components/AnimatedContent.tsx @@ -0,0 +1,21 @@ +import { IOnboardStepContentProps } from "./types"; + +export function AnimatedStepContent({ header, handleClick, message, index, length }: IOnboardStepContentProps) { + + return ( +
handleClick(index)} className="cursor-pointer grid grid-cols-[2.5rem_auto] gap-6 lg:gap-10 place-content-start place-items-start max-w-md"> +
+ {index + 1} + {index + 1 < length &&
} +
+
+

+ {header} +

+

+ {message} +

+
+
+ ) +} diff --git a/src/app/how-it-works/_components/AnimatedImage.tsx b/src/app/how-it-works/_components/AnimatedImage.tsx new file mode 100644 index 0000000..e12889d --- /dev/null +++ b/src/app/how-it-works/_components/AnimatedImage.tsx @@ -0,0 +1,18 @@ +import Image from "next/image"; +import { IOnboardStepImageProps } from "./types"; + +export function AnimatedStepImage({ className = "", ImageSrc, handleClick, alt, step, index }: IOnboardStepImageProps) { + const isActive = step === index; + + return ( +
handleClick(index)} className={`cursor-pointer ${className} absolute inset-0 flex items-center justify-center sm:justify-end transition-[transform_opacity] duration-1000 ease-in-out`} + style={{ transform: `rotate(${isActive ? 0 : 45}deg) scale(${isActive ? 1 : 0})`, opacity: `${isActive ? 100 : 0}%` }} + > +
+ {alt} +
+
+ + ) +} diff --git a/src/app/how-it-works/_components/Button.tsx b/src/app/how-it-works/_components/Button.tsx new file mode 100644 index 0000000..9fbaabc --- /dev/null +++ b/src/app/how-it-works/_components/Button.tsx @@ -0,0 +1,15 @@ +import Link from "next/link"; +import { ReactNode } from "react"; + +function Button({ children, href, className }: { className: string, children: ReactNode, href: string }) { + return ( + + {children} + + ) +} + + + +export default Button; + diff --git a/src/app/how-it-works/_components/FaqSection.tsx b/src/app/how-it-works/_components/FaqSection.tsx new file mode 100644 index 0000000..996c9b6 --- /dev/null +++ b/src/app/how-it-works/_components/FaqSection.tsx @@ -0,0 +1,76 @@ +"use client" + +import { Dispatch, SetStateAction, useState } from "react"; +import { BiMinusCircle, BiPlusCircle } from "react-icons/bi"; + +const faqItems = [ + { + question: "How to create an account on ChaineLib", + answer: "Get a unique NFT-powered author profile with your bio, genres, and publishing rights.\n\nGet a unique NFT-powered author profile with your bio, genres, and publishing rights." + }, + { + question: "How to create an account on ChaineLib", + answer: "Get a unique NFT-powered author profile with your bio, genres, and publishing rights.\n\nGet a unique NFT-powered author profile with your bio, genres, and publishing rights." + }, + { + question: "How to create an account on ChaineLib", + answer: "Get a unique NFT-powered author profile with your bio, genres, and publishing rights.\n\nGet a unique NFT-powered author profile with your bio, genres, and publishing rights." + }, + { + question: "How to create an account on ChaineLib", + answer: "Get a unique NFT-powered author profile with your bio, genres, and publishing rights.\n\nGet a unique NFT-powered author profile with your bio, genres, and publishing rights." + }, + { + question: "How to create an account on ChaineLib", + answer: "Get a unique NFT-powered author profile with your bio, genres, and publishing rights.\n\nGet a unique NFT-powered author profile with your bio, genres, and publishing rights." + }, +]; + +export default function FaqSection() { + const [clicked, setClicked] = useState(1); + + return ( +
+

+ You Got Questions? +

+ +
+ {faqItems.map((item, index) => ( + + ))} +
+
+ ) +} + + +function FaqItem({ question, answer, index, setClicked, clicked }: { question: string, answer: string, index: number, setClicked: Dispatch>, clicked: number }) { + function handleClick() { + if (index === clicked) { setClicked(0) } + else { setClicked(index) } + } + + return ( +
+

+ + {question} + + + {clicked === index ? : } + +

+

+ {answer} +

+
+ ) +} diff --git a/src/app/how-it-works/_components/Footer.tsx b/src/app/how-it-works/_components/Footer.tsx new file mode 100644 index 0000000..672f0c6 --- /dev/null +++ b/src/app/how-it-works/_components/Footer.tsx @@ -0,0 +1,68 @@ +import Link from "next/link"; +import { BiLogoLinkedin, BiLogoTelegram } from "react-icons/bi"; +import { FaXTwitter } from "react-icons/fa6"; +import Logo from "./Logo"; + +export interface IFooterLinks { + link: string; + href: string; +} + +const FooterLink: IFooterLinks[] = [ + { link: "Explore", href: "/explore" }, + { link: "Home", href: "/" }, + { link: "Books", href: "/books" }, + { link: "How It Works", href: "/how-it-works" }, + { link: "About", href: "/about-us" }, + { link: "Legal", href: "/legal" }, + { link: "Privacy Policy", href: "/privacy-policy" }, + { link: "Terms Of Service", href: "/terms-of-service" }, +]; + + +export default function Footer() { + const currentYear = new Date().getFullYear(); + + return ( +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+ © {currentYear}{" "}ChainLib. All rights reserved +
+
+ +
+ {FooterLink.map(({ link, href }, index) => {link})} +
+ +
+
+
+ +
+
+ +
+
+ +
+
+
+ 2025{" "}ChainLib. All rights reserved +
+
+
+ ) +} diff --git a/src/app/how-it-works/_components/LoginStep.tsx b/src/app/how-it-works/_components/LoginStep.tsx new file mode 100644 index 0000000..7aa6995 --- /dev/null +++ b/src/app/how-it-works/_components/LoginStep.tsx @@ -0,0 +1,79 @@ +"use client" + +import { Ref, useState } from 'react'; +import { AnimatedStepContent } from './AnimatedContent'; +import { AnimatedStepImage } from './AnimatedImage'; +import { IOnboardStepProps } from './types'; + +const loginSteps: IOnboardStepProps[] = [ + { + message: "Sign up quickly with your wallet and start exploring.", + alt: "Sign up and connect wallet image", + header: "Join & Connect Wallet", + ImageSrc: "./LoginSteps/LoginStep1.svg", + }, + { + message: + "Choose your favorite genre, set reading goals and follow your favorite author", + alt: "Sign up and connect wallet image", + header: "Personalize Your Profile", + ImageSrc: "./LoginSteps/LoginStep2.svg", + }, + { + message: + "Browse trending titles, new releases, and exclusive collections curated for you", + alt: "Sign up and connect wallet image", + header: "Discover Content", + ImageSrc: "./LoginSteps/LoginStep3.svg", + }, + { + message: + "Read online , offline, or own a special edition NFT of your favorite book", + alt: "Sign up and connect wallet image", + header: "Read or Collect", + ImageSrc: "./LoginSteps/LoginStep4.svg", + }, + { + message: + "Leave reviews, earn achievements, join book clubs, and climb the reader ranks", + alt: "Sign up and connect wallet image", + header: "Engage & Level Up", + ImageSrc: "./LoginSteps/LoginStep5.svg", + }, + { + message: "Support Authors Directly", + alt: "Sign up and connect wallet image", + header: + "Every read and purchase supports the creator. Collect, recommend, and enjoy the community", + ImageSrc: "./LoginSteps/LoginStep6.svg", + }, +]; + +export default function LoginStep({ readerRef }: { readerRef: Ref }) { + // The first step is at 0, same with the index + const [step, setStep] = useState(0) + + const handleClick = (index: number) => { + if (loginSteps.length > index + 1) { + setStep(() => index + 1) + } else { + setStep(() => 0) + } + } + + return ( +
+
+ {loginSteps.map(({ ImageSrc, alt }, index) => ())} +
+ +
+
+ {loginSteps.map(({ message, header }, index) => ())} +
+
+
+ ) +} diff --git a/src/app/how-it-works/_components/Logo.tsx b/src/app/how-it-works/_components/Logo.tsx new file mode 100644 index 0000000..7ba0f03 --- /dev/null +++ b/src/app/how-it-works/_components/Logo.tsx @@ -0,0 +1,14 @@ +import { cn } from "@/lib/utils"; +import Image from "next/image"; +import Link from "next/link"; + +export default function Logo({ className = "" }: { className?: string }) { + return ( + +
+ The Chainlib Logo +
+
ChainLib
+ + ) +} diff --git a/src/app/how-it-works/_components/NavLink.tsx b/src/app/how-it-works/_components/NavLink.tsx new file mode 100644 index 0000000..8facfd2 --- /dev/null +++ b/src/app/how-it-works/_components/NavLink.tsx @@ -0,0 +1,12 @@ +"use client" + +import Link from "next/link"; +import { usePathname } from "next/navigation"; +import { ReactNode } from "react"; + +export default function NavLink({ children, href }: { children: ReactNode, href: string }) { + const pathname = usePathname() + return ( + {children} + ) +} diff --git a/src/app/how-it-works/_components/NavMenu.tsx b/src/app/how-it-works/_components/NavMenu.tsx new file mode 100644 index 0000000..d8a6f69 --- /dev/null +++ b/src/app/how-it-works/_components/NavMenu.tsx @@ -0,0 +1,54 @@ +import { motion, Variants } from "framer-motion"; +import Link from "next/link"; +import { ILink } from "./types"; + +const animateFn = (variants: Variants, custom: number | null = null) => { + return { + initial: "initial", + animate: "enter", + exit: "exit", + custom, + variants, + }; +}; + +const links: ILink[] = [ + { link: "Home", href: "/" }, + { link: "Books", href: "/books/bookId" }, + { link: "How It Works", href: "/how-it-works" }, + { link: "About ChainLib", href: "/about-us" }, +]; + +export default function NavMenu() { + const opacity = { + initial: { + y: "100%", + }, + animate: (i: number) => ({ + y: "0%", + transition: { duration: 0.5, delay: 0.01 * i + 0.3 }, + }), + exit: { + y: "100%", + transition: { duration: 0.2 }, + }, + }; + + return ( + +
+ {links.map(({ link, href }, index) => + ( + {link} + ) + )} +
+
+ ) +} diff --git a/src/app/how-it-works/_components/NavMenuButton.tsx b/src/app/how-it-works/_components/NavMenuButton.tsx new file mode 100644 index 0000000..df1a75a --- /dev/null +++ b/src/app/how-it-works/_components/NavMenuButton.tsx @@ -0,0 +1,26 @@ +"use client" + +import { AnimatePresence } from "framer-motion" +import { useState } from "react" +import NavMenu from "./NavMenu" + +export default function NavMenuButton() { + const [openMenu, setOpenMenu] = useState(false) + + function handleMenuClick() { + setOpenMenu(t => !t) + } + return ( + <> + + + + {openMenu && } + + + ) +} diff --git a/src/app/how-it-works/_components/NavSearchBar.tsx b/src/app/how-it-works/_components/NavSearchBar.tsx new file mode 100644 index 0000000..50be45b --- /dev/null +++ b/src/app/how-it-works/_components/NavSearchBar.tsx @@ -0,0 +1,44 @@ +"use client" + +import { cn } from "@/lib/utils" +import { FormEvent, useEffect, useRef, useState } from "react" +import { BiSolidSearch } from "react-icons/bi" + +function NavSearchBar() { + const [active, setActive] = useState(false) + + const searchRef = useRef(null) + + useEffect(() => { + function handleClickOutside(event: MouseEvent) { + if (searchRef.current && !(searchRef.current).contains(event.target as Node)) { + setActive(false) + } + } + + document.addEventListener("mousedown", handleClickOutside) + return () => document.removeEventListener("mousedown", handleClickOutside) + }, []) + + const handleSubmit = (e: FormEvent) => { + e.preventDefault() + setActive(false) + } + + return ( +
setActive(() => true)} className={cn( + "cursor-pointer hover:bg-neutral-50 border border-neutral-300 py-3 px-3.5 rounded-small text-neutral-300 shadow-base flex items-center transition-all duration-300 ease-in-out", + { "bg-neutral-50": active } + )}> + +
+ +
+ + ) +} + +export default NavSearchBar \ No newline at end of file diff --git a/src/app/how-it-works/_components/Navbar.tsx b/src/app/how-it-works/_components/Navbar.tsx new file mode 100644 index 0000000..724f248 --- /dev/null +++ b/src/app/how-it-works/_components/Navbar.tsx @@ -0,0 +1,42 @@ + +import Button from "./Button"; +import Logo from "./Logo"; +import NavLink from "./NavLink"; +import NavMenuButton from "./NavMenuButton"; +import NavSearchBar from "./NavSearchBar"; + +interface ILink { + link: string; + href: string; +} + +const links: ILink[] = [ + { link: "Home", href: "/" }, + { link: "Books", href: "/books/bookId" }, + { link: "How It Works", href: "/how-it-works" }, + { link: "About ChainLib", href: "/about-us" }, +]; + +function Navbar() { + return ( + + ) +} + +export default Navbar \ No newline at end of file diff --git a/src/app/how-it-works/_components/SelectChoiceButton.tsx b/src/app/how-it-works/_components/SelectChoiceButton.tsx new file mode 100644 index 0000000..229db84 --- /dev/null +++ b/src/app/how-it-works/_components/SelectChoiceButton.tsx @@ -0,0 +1,13 @@ +export default function SelectChoiceButton({ writerIsActive, scrollToSection }: { writerIsActive: boolean, scrollToSection: (value: string) => void }) { + + return ( +
+ + +
+ ) +} diff --git a/src/app/how-it-works/_components/SignupStep.tsx b/src/app/how-it-works/_components/SignupStep.tsx new file mode 100644 index 0000000..eabeb54 --- /dev/null +++ b/src/app/how-it-works/_components/SignupStep.tsx @@ -0,0 +1,84 @@ +"use client" + +import { Ref, useState } from 'react'; +import { AnimatedStepContent } from './AnimatedContent'; +import { AnimatedStepImage } from './AnimatedImage'; +import { IOnboardStepProps } from './types'; + +const signupSteps: IOnboardStepProps[] = [ + { + alt: "Sign up and connect wallet image", + header: "Sign Up & Connect Wallet", + message: + "Join ChainLib as a writer by connecting your StarkNet wallet(e.g., Braavos or Argent).", + ImageSrc: "./SignupSteps/SignUpStep1.svg", + }, + { + message: + "Get a Unique NFT-powered author profile with your bio, genres, and publishing rights", + alt: "Sign up and connect wallet image", + header: "Create Your Author Identity", + ImageSrc: "./SignupSteps/SignUpStep2.svg", + }, + { + message: + "Sign a smart contract that outlines ownership rights and revenue sharing.", + alt: "Sign up and connect wallet image", + header: "Agree To Terms", + ImageSrc: "./SignupSteps/SignUpStep3.svg", + }, + { + message: + "Access your personal dashboard to manage books, track earnings and engage with readers.", + alt: "Sign up and connect wallet image", + header: "Set Up Your Dashboard", + ImageSrc: "./SignupSteps/SignUpStep4.svg", + }, + { + message: + "Upload your book, add metadata(title, genre, price), and mint it as a content NFT.", + alt: "Sign up and connect wallet image", + header: "Publish your Books", + ImageSrc: "./SignupSteps/SignUpStep5.svg", + }, + { + message: + "Earn instantly from purchases or subscriptions no middleman, full transparency", + alt: "Sign up and connect wallet image", + header: "Get Paid Directly", + ImageSrc: "./SignupSteps/SignUpStep6.svg", + }, +]; + +export default function SignupStep({ writerRef }: { writerRef: Ref }) { + // The first step is at 0, same with the index + const [step, setStep] = useState(0) + + const handleClick = (index: number) => { + if (signupSteps.length > index + 1) { + setStep(() => index + 1) + } else { + setStep(() => 0) + } + } + + return ( +
+
+
+ {signupSteps.map(({ message, header }, index) => ())} +
+
+ +
+ {signupSteps.map(({ ImageSrc, alt }, index) => ())} +
+
+ ) +} + + + + diff --git a/src/app/how-it-works/_components/StepByStepSection.tsx b/src/app/how-it-works/_components/StepByStepSection.tsx new file mode 100644 index 0000000..bc7462d --- /dev/null +++ b/src/app/how-it-works/_components/StepByStepSection.tsx @@ -0,0 +1,36 @@ +"use client" + +import { useRef, useState } from "react"; +import LoginStep from "./LoginStep"; +import SelectChoiceButton from "./SelectChoiceButton"; +import SignupStep from "./SignupStep"; + +export default function StepByStepSection() { + const [writerIsActive, setWriterIsActive] = useState(true) + const writerRef = useRef(null) + const readerRef = useRef(null) + + const scrollToSection = (section: string) => { + if (section === "writer") { + writerRef.current?.scrollIntoView({ behavior: "smooth", block: "center" }); + setWriterIsActive(() => true) + } else { + readerRef.current?.scrollIntoView({ behavior: "smooth", block: "nearest" }); + setWriterIsActive(() => false) + } + }; + + return ( +
+
+ + + {/* Signup steps */} + +
+ + {/* Login Steps */} + +
+ ) +} diff --git a/src/app/how-it-works/_components/types.ts b/src/app/how-it-works/_components/types.ts new file mode 100644 index 0000000..8cfb226 --- /dev/null +++ b/src/app/how-it-works/_components/types.ts @@ -0,0 +1,34 @@ +export interface ILink { + link: string; + href: string; +} + +export interface IFooterLinks { + link: string; + href: string; +} + +export interface IOnboardStepContentProps { + header: string; + message: string; + index: number; + handleClick: (index: number) => void; + length: number; +} + +export interface IOnboardStepImageProps { + alt: string; + className?: string; + ImageSrc: string; + index: number; + handleClick: (index: number) => void; + length: number; + step: number; +} + +export interface IOnboardStepProps { + alt: string; + ImageSrc: string; + header: string; + message: string; +} diff --git a/src/app/how-it-works/page.tsx b/src/app/how-it-works/page.tsx new file mode 100644 index 0000000..1e7b819 --- /dev/null +++ b/src/app/how-it-works/page.tsx @@ -0,0 +1,30 @@ +import FaqSection from "./_components/FaqSection"; +import Footer from "./_components/Footer"; +import Navbar from "./_components/Navbar"; +import StepByStepSection from "./_components/StepByStepSection"; + +export default function Page() { + + return ( + <> + + +
+

+ Building More +
+ Than an e-Library +

+

A decentralized world where stories live on-chain and creators stay in control. Powered by StarkNet, our platform gives writers the freedom to publish without intermediaries and gives readers direct access to original, verifiable content they can truly own.

+
+ + + +
+ +
+ +