diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 43f2d88..54fb350 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,3 @@ - - # Contributing Guidelines Thank you for your interest in contributing to our project! To maintain consistency and quality across the codebase, please follow these guidelines when contributing. diff --git a/package-lock.json b/package-lock.json index fd03d45..9a0b63c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -964,9 +964,9 @@ } }, "node_modules/@remix-run/router": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.2.tgz", - "integrity": "sha512-baiMx18+IMuD1yyvOGaHM9QrVUPGGG0jC+z+IPHnRJWUAUvaKuWKyE8gjDj2rzv3sz9zOGoRSPgeBVHRhZnBlA==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.20.0.tgz", + "integrity": "sha512-mUnk8rPJBI9loFDZ+YzPGdeniYK+FTmRD1TMCz7ev2SNIozyKKpnGgsxO34u6Z4z/t0ITuu7voi/AshfsGsgFg==", "engines": { "node": ">=14.0.0" } @@ -1429,7 +1429,6 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "license": "MIT", "engines": { "node": ">=6" } @@ -1700,9 +1699,9 @@ } }, "node_modules/framer-motion": { - "version": "11.11.1", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.11.1.tgz", - "integrity": "sha512-Ucr9eHSrk0d+l6vyl9fvq6omh/PAWHjS+PlczpsoUdhJo1TuF3ULWJNuAMnpWQ1dGyPOyoUVuYlUKjE/s8dyCA==", + "version": "11.11.9", + "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.11.9.tgz", + "integrity": "sha512-XpdZseuCrZehdHGuW22zZt3SF5g6AHJHJi7JwQIigOznW4Jg1n0oGPMJQheMaKLC+0rp5gxUKMRYI6ytd3q4RQ==", "dependencies": { "tslib": "^2.4.0" }, @@ -1826,8 +1825,7 @@ "node_modules/gsap": { "version": "3.12.5", "resolved": "https://registry.npmjs.org/gsap/-/gsap-3.12.5.tgz", - "integrity": "sha512-srBfnk4n+Oe/ZnMIOXt3gT605BX9x5+rh/prT2F1SsNJsU1XuMiP0E2aptW481OnonOGACZWBqseH5Z7csHxhQ==", - "license": "Standard 'no charge' license: https://gsap.com/standard-license. Club GSAP members get more: https://gsap.com/licensing/. Why GreenSock doesn't employ an MIT license: https://gsap.com/why-license/" + "integrity": "sha512-srBfnk4n+Oe/ZnMIOXt3gT605BX9x5+rh/prT2F1SsNJsU1XuMiP0E2aptW481OnonOGACZWBqseH5Z7csHxhQ==" }, "node_modules/has-flag": { "version": "3.0.0", @@ -2540,11 +2538,11 @@ } }, "node_modules/react-router": { - "version": "6.26.2", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.26.2.tgz", - "integrity": "sha512-tvN1iuT03kHgOFnLPfLJ8V95eijteveqdOSk+srqfePtQvqCExB8eHOYnlilbOcyJyKnYkr1vJvf7YqotAJu1A==", + "version": "6.27.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.27.0.tgz", + "integrity": "sha512-YA+HGZXz4jaAkVoYBE98VQl+nVzI+cVI2Oj/06F5ZM+0u3TgedN9Y9kmMRo2mnkSK2nCpNQn0DVob4HCsY/WLw==", "dependencies": { - "@remix-run/router": "1.19.2" + "@remix-run/router": "1.20.0" }, "engines": { "node": ">=14.0.0" @@ -2554,12 +2552,12 @@ } }, "node_modules/react-router-dom": { - "version": "6.26.2", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.26.2.tgz", - "integrity": "sha512-z7YkaEW0Dy35T3/QKPYB1LjMK2R1fxnHO8kWpUMTBdfVzZrWOiY9a7CtN8HqdWtDUWd5FY6Dl8HFsqVwH4uOtQ==", + "version": "6.27.0", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.27.0.tgz", + "integrity": "sha512-+bvtFWMC0DgAFrfKXKG9Fc+BcXWRUO1aJIihbB79xaeq0v5UzfvnM5houGUm1Y461WVRcgAQ+Clh5rdb1eCx4g==", "dependencies": { - "@remix-run/router": "1.19.2", - "react-router": "6.26.2" + "@remix-run/router": "1.20.0", + "react-router": "6.27.0" }, "engines": { "node": ">=14.0.0" @@ -3242,7 +3240,6 @@ "version": "0.5.1", "resolved": "https://registry.npmjs.org/vite-plugin-compression/-/vite-plugin-compression-0.5.1.tgz", "integrity": "sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg==", - "license": "MIT", "dependencies": { "chalk": "^4.1.2", "debug": "^4.3.3", @@ -3513,10 +3510,16 @@ "@dfinity/auth-client": "^2.1.2", "@dfinity/candid": "^0.15.7", "@dfinity/principal": "^0.15.7", + "aos": "^2.3.4", + "clsx": "^2.1.1", + "framer-motion": "^11.11.9", + "gsap": "^3.12.5", "react": "^18.2.0", "react-dom": "^18.2.0", "react-hot-toast": "^2.4.1", - "react-icons": "^5.3.0" + "react-icons": "^5.3.0", + "react-router-dom": "^6.27.0", + "vite-plugin-compression": "^0.5.1" }, "devDependencies": { "@types/react": "^18.2.14", diff --git a/scripts/local.sh b/scripts/local.sh new file mode 100644 index 0000000..c3e700d --- /dev/null +++ b/scripts/local.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +# Start the local replica +dfx start --background + +# Install the project dependencies +npm install + +# Deploy the project +dfx deploy \ No newline at end of file diff --git a/src/StarDustAdventures_frontend/package.json b/src/StarDustAdventures_frontend/package.json index 6ef7b09..c858962 100644 --- a/src/StarDustAdventures_frontend/package.json +++ b/src/StarDustAdventures_frontend/package.json @@ -15,10 +15,16 @@ "@dfinity/auth-client": "^2.1.2", "@dfinity/candid": "^0.15.7", "@dfinity/principal": "^0.15.7", + "aos": "^2.3.4", + "clsx": "^2.1.1", + "framer-motion": "^11.11.9", + "gsap": "^3.12.5", "react": "^18.2.0", "react-dom": "^18.2.0", "react-hot-toast": "^2.4.1", - "react-icons": "^5.3.0" + "react-icons": "^5.3.0", + "react-router-dom": "^6.27.0", + "vite-plugin-compression": "^0.5.1" }, "devDependencies": { "@types/react": "^18.2.14", diff --git a/src/StarDustAdventures_frontend/src/components/landing-mobile/gameplayMechanics/Card/index.css b/src/StarDustAdventures_frontend/src/components/landing-mobile/gameplayMechanics/Card/index.css new file mode 100644 index 0000000..bbaf704 --- /dev/null +++ b/src/StarDustAdventures_frontend/src/components/landing-mobile/gameplayMechanics/Card/index.css @@ -0,0 +1,3 @@ +.mob-gameplay-card{ + @apply w-screen flex flex-col justify-start items-center gap-8 +} \ No newline at end of file diff --git a/src/StarDustAdventures_frontend/src/components/landing-mobile/gameplayMechanics/Card/index.tsx b/src/StarDustAdventures_frontend/src/components/landing-mobile/gameplayMechanics/Card/index.tsx new file mode 100644 index 0000000..e88613b --- /dev/null +++ b/src/StarDustAdventures_frontend/src/components/landing-mobile/gameplayMechanics/Card/index.tsx @@ -0,0 +1,22 @@ +import { CardProps } from "../../../landing/gamePlayMechanics/Cards"; +import './index.css'; + +/** + * A Card component that displays a gameplay mechanic. + * It includes an image, title, and description. + * + * @param {CardProps} props - The card properties. + * @param {string} props.title - The title of the card. + * @param {string} props.description - The description of the gameplay mechanic. + * @param {string} props.image - The image URL representing the gameplay mechanic. + * @returns {JSX.Element} A styled card with an image, title, and description. + */ +export default function Card({ title, description, image }: CardProps): JSX.Element { + return ( +
+ {title} +

{title}

+

{description}

+
+ ); +} diff --git a/src/StarDustAdventures_frontend/src/components/landing-mobile/gameplayMechanics/index.css b/src/StarDustAdventures_frontend/src/components/landing-mobile/gameplayMechanics/index.css new file mode 100644 index 0000000..a8ba482 --- /dev/null +++ b/src/StarDustAdventures_frontend/src/components/landing-mobile/gameplayMechanics/index.css @@ -0,0 +1,12 @@ +.mob-gameplay-container{ + @apply min-h-screen h-auto relative; +} + +.mob-gameplay-header{ + @apply relative h-screen min-h-fit flex flex-col justify-center z-[100]; + scroll-snap-align:center; +} + +.gameplay-mechanics-cards-list{ + @apply mt-4 flex justify-between items-center w-[300vw] +} \ No newline at end of file diff --git a/src/StarDustAdventures_frontend/src/components/landing-mobile/gameplayMechanics/index.tsx b/src/StarDustAdventures_frontend/src/components/landing-mobile/gameplayMechanics/index.tsx new file mode 100644 index 0000000..9edb877 --- /dev/null +++ b/src/StarDustAdventures_frontend/src/components/landing-mobile/gameplayMechanics/index.tsx @@ -0,0 +1,84 @@ +import { useEffect, useRef } from "react"; +import { CARDS } from "../../landing/gamePlayMechanics"; +import Card from "./Card"; +import './index.css'; +import gsap from "gsap"; +import { ScrollTrigger } from 'gsap/ScrollTrigger'; + +gsap.registerPlugin(ScrollTrigger); + +/** + * Renders the header for gameplay mechanics. + * @param {Object} props - Component props + * @param {React.RefObject} props.headerRef - Ref for the header container + */ +const Header = ({ headerRef }: { headerRef: React.RefObject }) => { + return ( +
+

Gameplay Mechanics

+

Explore the engaging system of Star Dust Adventures

+
+ ); +}; + +/** + * Renders a list of gameplay mechanic cards. + * @param {Object} props - Component props + * @param {React.RefObject} props.cardsRef - Ref for the cards container + */ +const CardList = ({ cardsRef }: { cardsRef: React.RefObject }) => { + return ( +
+ {CARDS.map((card, index) => ( + + ))} +
+ ); +}; + +/** + * Renders the Gameplay Mechanics section with GSAP animations and ScrollTrigger. + */ +const GameplayMechanics = () => { + const headerRef = useRef(null); + const containerRef = useRef(null); + const cardsRef = useRef(null); + + useEffect(() => { + if (headerRef.current && containerRef.current && cardsRef.current) { + const tl = gsap.timeline({ + scrollTrigger: { + trigger: containerRef.current, + start: "top top", + end: "bottom bottom", + scrub: true, + pin: true, + anticipatePin: 1, + } + }); + + // Header animation + tl.fromTo(headerRef.current, { x: '100%', height: '100vh' }, { x: 0, height: 0, duration: 1 }); + + // Cards animation + const cards = cardsRef.current.querySelectorAll(".mob-gameplay-card"); + tl.fromTo(cards, + { opacity: 0.8, scale: 0.8 }, + { xPercent: -100 * (cards.length - 1), ease: "none", opacity: 1, scale: 1 } + ); + + return () => { + ScrollTrigger.getAll().forEach(trigger => trigger.kill()); + }; + } + }, []); + + return ( +
+
+ +
+ ); +}; + +export default GameplayMechanics; diff --git a/src/StarDustAdventures_frontend/src/components/landing/GradientCover/index.css b/src/StarDustAdventures_frontend/src/components/landing/GradientCover/index.css index 040e4a6..c37c38e 100644 --- a/src/StarDustAdventures_frontend/src/components/landing/GradientCover/index.css +++ b/src/StarDustAdventures_frontend/src/components/landing/GradientCover/index.css @@ -1,5 +1,6 @@ .gradient-cover{ - @apply outline outline-lime-50 md:min-h-screen h-auto w-screen relative bg-black flex flex-col justify-between lg:gap-32 + @apply md:min-h-screen h-auto w-screen relative bg-black flex flex-col justify-between lg:gap-32; + scroll-snap-type: y mandatory; } .right-purple-pattern{ diff --git a/src/StarDustAdventures_frontend/src/components/landing/GradientCover/index.tsx b/src/StarDustAdventures_frontend/src/components/landing/GradientCover/index.tsx index defc1e7..d24ebfa 100644 --- a/src/StarDustAdventures_frontend/src/components/landing/GradientCover/index.tsx +++ b/src/StarDustAdventures_frontend/src/components/landing/GradientCover/index.tsx @@ -1,17 +1,25 @@ import React from 'react'; -import './index.css' -export default function Cover({children} : React.PropsWithChildren<{}>){ - return( +import './index.css'; + +/** + * A Cover component that wraps its children with a gradient background and patterned decorations. + * + * @param {React.PropsWithChildren<{}>} props - The props containing children elements. + * @param {React.ReactNode} props.children - The content to be rendered inside the cover. + * @returns {JSX.Element} A styled cover with children content. + */ +export default function Cover({ children }: React.PropsWithChildren<{}>): JSX.Element { + return (
- purple-pattern -
+ purple-pattern +
- blue-pattern -
+ blue-pattern +
{children}
- ) -} \ No newline at end of file + ); +} diff --git a/src/StarDustAdventures_frontend/src/components/landing/gamePlayMechanics/Cards/index.css b/src/StarDustAdventures_frontend/src/components/landing/gamePlayMechanics/Cards/index.css index c725681..6db89d1 100644 --- a/src/StarDustAdventures_frontend/src/components/landing/gamePlayMechanics/Cards/index.css +++ b/src/StarDustAdventures_frontend/src/components/landing/gamePlayMechanics/Cards/index.css @@ -1,6 +1,6 @@ .gameplay-card{ @apply relative flex flex-col lg:px-3 lg:py-4 justify-start items-center - bg-transparent lg:gap-7 text-white lg:h-[50vh] z-[1] md:w-auto w-screen + bg-transparent lg:gap-7 text-white lg:h-[50vh] z-[1] w-auto } .card-title{ diff --git a/src/StarDustAdventures_frontend/src/components/landing/gamePlayMechanics/Cards/index.tsx b/src/StarDustAdventures_frontend/src/components/landing/gamePlayMechanics/Cards/index.tsx index 01dcf71..061865e 100644 --- a/src/StarDustAdventures_frontend/src/components/landing/gamePlayMechanics/Cards/index.tsx +++ b/src/StarDustAdventures_frontend/src/components/landing/gamePlayMechanics/Cards/index.tsx @@ -6,16 +6,19 @@ export type CardProps = { image : string; } -/* - * Card Component - * - Component that renders a card with an image, title, and description - * - Returns a div with an image, title, and description - * - Used in Landing Page -*/ - +/** + * A Card component that displays a gameplay mechanic for desktop view. + * It includes an image, title, and description. + * + * @param {CardProps} props - The card properties. + * @param {string} props.title - The title of the card. + * @param {string} props.description - The description of the gameplay mechanic. + * @param {string} props.image - The image URL representing the gameplay mechanic. + * @returns {JSX.Element} A styled card with an image, title, and description for large screen sizes ( > 768px). + */ const Card = ({title, description,image}:CardProps)=>{ return( -
+
{title}

{title}

{description}

diff --git a/src/StarDustAdventures_frontend/src/components/landing/gamePlayMechanics/index.css b/src/StarDustAdventures_frontend/src/components/landing/gamePlayMechanics/index.css index 61e7fcb..ef6a55e 100644 --- a/src/StarDustAdventures_frontend/src/components/landing/gamePlayMechanics/index.css +++ b/src/StarDustAdventures_frontend/src/components/landing/gamePlayMechanics/index.css @@ -1,6 +1,5 @@ .gameplay-mechanics { - @apply w-full bg-transparent lg:mt-24 mt-12 text-white flex flex-col items-center justify-center py-3 md:min-h-min min-h-screen md:max-h-screen h-auto relative - + @apply w-full bg-transparent lg:mt-24 mt-12 text-white flex flex-col items-center justify-center py-3 max-h-screen h-auto relative ; } @@ -9,8 +8,8 @@ } .gameplay-mechanics-cards { - @apply flex md:flex-1 flex-row md:justify-between justify-center md:items-center items-center gap-6 relative mt-2 md:w-full w-[300vw] md:h-auto h-screen - overflow-x-hidden px-2 outline outline-red-500 ; + @apply flex md:flex-1 flex-row md:justify-between justify-center md:items-center items-center gap-6 relative mt-2 w-full h-auto + overflow-x-hidden px-2 ; } .section-title { diff --git a/src/StarDustAdventures_frontend/src/components/landing/gamePlayMechanics/index.tsx b/src/StarDustAdventures_frontend/src/components/landing/gamePlayMechanics/index.tsx index f92074b..067e9ed 100644 --- a/src/StarDustAdventures_frontend/src/components/landing/gamePlayMechanics/index.tsx +++ b/src/StarDustAdventures_frontend/src/components/landing/gamePlayMechanics/index.tsx @@ -1,4 +1,4 @@ -import { useRef, useEffect, useState } from 'react'; +import { useRef, useEffect} from 'react'; import GameplayMechanic, { CardProps } from './Cards'; import gsap from 'gsap'; import { ScrollTrigger } from 'gsap/ScrollTrigger'; @@ -8,126 +8,112 @@ import React from 'react'; gsap.registerPlugin(ScrollTrigger); // Card Static Data -const CARDS = [ - { - title: "Core Gameplay Loop", - description: 'Players tap to mine StarDust, with oxygen consumption renewed every 8 hours.', - image: '/assets/images/mars.svg' - }, - { - title: "Progression Opportunities", - description: "Upgrade astronaut's oxygen tank, mining tool, & storage to unlock richer resources.", - image: '/assets/images/moon.svg' - }, - { - title: "Play-to-Earn System", - description: "Accumulate StarDust, converting it to a future token tradable on exchanges for financial rewards.", - image: '/assets/images/earth.svg' - } -] as CardProps[]; +export const CARDS: CardProps[] = [ + { + title: "Core Gameplay Loop", + description: 'Players tap to mine StarDust, with oxygen consumption renewed every 8 hours.', + image: '/assets/images/mars.svg', + }, + { + title: "Progression Opportunities", + description: "Upgrade astronaut's oxygen tank, mining tool, & storage to unlock richer resources.", + image: '/assets/images/moon.svg', + }, + { + title: "Play-to-Earn System", + description: "Accumulate StarDust, converting it to a future token tradable on exchanges for financial rewards.", + image: '/assets/images/earth.svg', + }, +]; -const Header = ({titleRef}:{titleRef : React.RefObject}) => { - return ( -
-

Gameplay Mechanics

-

Explore the engaging system of Star Dust Adventures

-
- ) -} +/** + * Renders the header section for the gameplay mechanics. + * @returns {JSX.Element} The header with a title and caption. + */ +const Header = (): JSX.Element => { + return ( +
+

Gameplay Mechanics

+

Explore the engaging system of Star Dust Adventures

+
+ ); +}; -type GamePlayCardListProps = { - containerRef : React.RefObject, - linesRef : React.RefObject -} +export type GamePlayCardListProps = { + containerRef: React.RefObject; + linesRef: React.MutableRefObject; +}; -const GamePlayCardList = ({ containerRef, linesRef } : GamePlayCardListProps) => { - return ( -
- {CARDS.map((card, index) => ( - - - {(index < CARDS.length - 1) && ( // Validate `linesRef.current` is not null -
el && (linesRef.current[index] = el)}>
// Assign ref after validating that linesRef.current is not null - )} -
- ))} -
- ) -} +/** + * Renders a list of gameplay cards with connecting lines. + * @param {GamePlayCardListProps} props - Props containing container and lines refs. + * @returns {JSX.Element} A list of cards with animated lines. + */ +const GamePlayCardList = ({ containerRef, linesRef }: GamePlayCardListProps): JSX.Element => { + return ( +
+ {CARDS.map((card, index) => ( + + + {index < CARDS.length - 1 && ( +
el && linesRef.current && (linesRef.current[index] = el)} // Validate `linesRef.current` + >
+ )} +
+ ))} +
+ ); +}; -const GamePlayMechanics = () => { - const containerRef = useRef(null); - const sectionRef = useRef(null); - const linesRef = useRef>([]); - const titleRef = useRef(null); +/** + * Main component for rendering the gameplay mechanics section, handling both desktop and mobile views. + * @returns {JSX.Element} The gameplay mechanics section with animations. + */ +const GamePlayMechanics = (): JSX.Element => { + const containerRef = useRef(null); + const sectionRef = useRef(null); + const linesRef = useRef([]); - const [isMobile,setIsMobile] = useState(window.innerWidth < 768); + // GSAP Animation Hook + useEffect(() => { + if (!containerRef.current || !sectionRef.current) return; + + const cards = containerRef.current.querySelectorAll('.gameplay-card'); + const lines = linesRef.current; - useEffect(()=>{ - window.addEventListener('resize',()=>{ - setIsMobile(window.innerWidth < 768); - }); - return () => { - window.removeEventListener('resize',()=>{}); - } - },[]); + // Set initial animation properties + gsap.set(cards, { opacity: 0, scale: 0.8 }); + gsap.set(lines, { scaleX: 0 }); - useEffect(() => { - if (!containerRef.current || !sectionRef.current || !titleRef.current) return; - const cards = containerRef.current.querySelectorAll('.gameplay-card'); - const lines = linesRef.current; - console.log(cards) + // Timeline for animation + const tl = gsap.timeline({ + scrollTrigger: { + trigger: sectionRef.current, + start: 'top top', + end: 'bottom top', + pin: true, + pinSpacing: true, + scrub: 1, + }, + }); + tl.to(cards, { opacity: 1, scale: 1, stagger: 0.2, duration: 0.5 }) + .to(lines, { scaleX: 1, duration: 0.5, stagger: 0.2 }, '<'); - - - // Screen based Animation - if(!isMobile){ - gsap.set(cards, { opacity: 0, scale: 0.8 }); - gsap.set(lines, { scaleX: 0 }); - const tl = gsap.timeline({ - scrollTrigger: { - trigger: sectionRef.current, - start: 'top top', - end: 'bottom top', - pin: true, - pinSpacing: true, - scrub: 1, - }, - }); - // Desktop Animation - tl.to(cards, { opacity: 1, scale: 1, stagger: 0.2, duration: 0.5 }) - .to(lines, { scaleX: 1, duration: 0.5, stagger: 0.2 }, '<'); - } else{ - // Cards Scroll based Animation + // Cleanup ScrollTriggers on unmount + return () => { + ScrollTrigger.getAll().forEach((trigger) => trigger.kill()); + }; + }, []); - gsap.to(cards,{ - xPercent: - 100 * (cards.length -1), - scale:1.2, - ease : "none", - scrollTrigger:{ - trigger:sectionRef.current, - pin:true, - scrub : 1, - // snap : 1 / (cards.length - 1), - end : () => sectionRef.current ? "+=" + sectionRef.current.offsetWidth / 3 : "+=0", - markers:true - } - }) - - } - return () => { - ScrollTrigger.getAll().forEach((trigger) => trigger.kill()); - }; - }, [isMobile]); - return ( -
-
- -
- ); + return( +
+
+ +
+ ); }; -export default GamePlayMechanics; \ No newline at end of file +export default GamePlayMechanics; diff --git a/src/StarDustAdventures_frontend/src/components/landing/hero/Hero.jsx b/src/StarDustAdventures_frontend/src/components/landing/hero/Hero.jsx index 9357065..5910a2d 100644 --- a/src/StarDustAdventures_frontend/src/components/landing/hero/Hero.jsx +++ b/src/StarDustAdventures_frontend/src/components/landing/hero/Hero.jsx @@ -1,57 +1,20 @@ -import React, { useEffect } from 'react' -import Button from '../../re-usables/Button' -import './hero.css' -import BgOverlay from '../../re-usables/BgOverlay' -import { motion } from 'framer-motion' +import React from 'react'; +import Button from '../../re-usables/Button'; +import BackgroundSection from './HeroBackground'; +import TextContent from './HeroTitleSection'; +import AstronautAnimation from './HeroVisual'; +import AdditionalText from './HeroDescription'; +import './hero.css'; const Hero = () => { return ( -
- {/* To Optimize Background Image Load */} - hero - - -

- Star Dust -

-

- Adventures -

-

- A Space Exploration Tap-to-Earn Game Powered By Crypto -

- -
- - { - window.innerWidth>1024? -
-

- Overview of Star Dust Adventures -

-

- A Tap-to-Earn Game Combining Exploration and Blockchain -

-
- : - <> - } - +
+ + + +
- ) -} + ); +}; -export default Hero \ No newline at end of file +export default Hero; diff --git a/src/StarDustAdventures_frontend/src/components/landing/hero/HeroBackground.jsx b/src/StarDustAdventures_frontend/src/components/landing/hero/HeroBackground.jsx new file mode 100644 index 0000000..853643d --- /dev/null +++ b/src/StarDustAdventures_frontend/src/components/landing/hero/HeroBackground.jsx @@ -0,0 +1,13 @@ +import React from 'react'; +import BgOverlay from '../../re-usables/BgOverlay'; + +const BackgroundSection = ({ image }) => { + return ( +
+ background + +
+ ); +}; + +export default BackgroundSection; diff --git a/src/StarDustAdventures_frontend/src/components/landing/hero/HeroDescription.jsx b/src/StarDustAdventures_frontend/src/components/landing/hero/HeroDescription.jsx new file mode 100644 index 0000000..0272261 --- /dev/null +++ b/src/StarDustAdventures_frontend/src/components/landing/hero/HeroDescription.jsx @@ -0,0 +1,23 @@ +import React, { useEffect, useState } from 'react'; + +const AdditionalText = () => { + const [isDesktop, setIsDesktop] = useState(window.innerWidth > 1024); + + useEffect(() => { + const handleResize = () => setIsDesktop(window.innerWidth > 1024); + window.addEventListener('resize', handleResize); + + return () => window.removeEventListener('resize', handleResize); + }, []); + + return ( +
+

Overview of Star Dust Adventures

+

+ A Tap-to-Earn Game Combining Exploration and Blockchain +

+
+ ); +}; + +export default AdditionalText; diff --git a/src/StarDustAdventures_frontend/src/components/landing/hero/HeroTitleSection.jsx b/src/StarDustAdventures_frontend/src/components/landing/hero/HeroTitleSection.jsx new file mode 100644 index 0000000..37f25a0 --- /dev/null +++ b/src/StarDustAdventures_frontend/src/components/landing/hero/HeroTitleSection.jsx @@ -0,0 +1,23 @@ +import React from 'react'; +import { motion } from 'framer-motion'; +import Button from '../../re-usables/Button'; + +const TextContent = () => { + return ( + +

Star Dust

+

Adventures

+

+ A Space Exploration Tap-to-Earn Game Powered By Crypto +

+ +
+ ); +}; + +export default TextContent; diff --git a/src/StarDustAdventures_frontend/src/components/landing/hero/HeroVisual.jsx b/src/StarDustAdventures_frontend/src/components/landing/hero/HeroVisual.jsx new file mode 100644 index 0000000..0199755 --- /dev/null +++ b/src/StarDustAdventures_frontend/src/components/landing/hero/HeroVisual.jsx @@ -0,0 +1,18 @@ +import React from 'react'; +import { motion } from 'framer-motion'; + +const AstronautAnimation = () => { + return ( + + ); +}; + +export default AstronautAnimation; diff --git a/src/StarDustAdventures_frontend/src/components/landing/hero/hero.css b/src/StarDustAdventures_frontend/src/components/landing/hero/hero.css index cf635a3..1bdd73b 100644 --- a/src/StarDustAdventures_frontend/src/components/landing/hero/hero.css +++ b/src/StarDustAdventures_frontend/src/components/landing/hero/hero.css @@ -1,43 +1,69 @@ -.hero-sec{ - @apply w-screen min-h-screen h-auto relative flex flex-col items-center overflow-x-hidden +.hero-section { + @apply w-screen min-h-screen h-auto relative flex flex-col items-center overflow-x-hidden; } -.hs-top-nav{ - @apply z-20 relative bg-[rgb(255,255,255,0.2)] py-8 flex items-center justify-center w-[98%] rounded-2xl + +.hero-top-nav { + @apply z-20 relative bg-[rgba(255,255,255,0.2)] py-8 flex items-center justify-center w-[98%] rounded-2xl; } -.hstp-text{ - @apply text-4xl font-semibold font-coin + +.hero-top-nav-text { + @apply text-4xl font-semibold font-coin; } -.hstp-btn{ - @apply justify-self-end absolute top-[2rem] right-[5vw] text-xl + +.hero-top-nav-button { + @apply absolute top-[2rem] right-[5vw] text-xl; } -.hs-text-cont{ - @apply flex flex-col items-center gap-5 mt-[20vh] z-20 + +.hero-text-content { + @apply flex flex-col items-center gap-5 mt-[20vh] z-20; } -.hstc-title{ - @apply lg:text-9xl text-6xl xs:text-6xl sm:text-7xl md:text-8xl lg:w-[50vw] w-full font-medium text-center mb-6 font-coin + +.hero-title-main { + @apply lg:text-9xl text-6xl xs:text-6xl sm:text-7xl md:text-8xl lg:w-[90vw] w-full font-medium text-center mb-6 font-coin; } -.hstc-title1{ - @apply lg:text-9xl text-6xl xs:text-6xl sm:text-7xl md:text-8xl lg:w-[50vw] w-full font-medium text-center mb-0 font-coin + +.hero-title-sub { + @apply lg:text-9xl text-6xl xs:text-6xl sm:text-7xl md:text-8xl lg:w-[65vw] w-full font-medium text-center mb-0 font-coin; } -.play-button{ - @apply !text-2xl !min-w-32 w-20 xs:!min-w-40 xs:w-32 xs:!text-3xl md:!min-w-[185px] md:!text-4xl + +.play-button { + @apply !text-2xl !min-w-32 w-20 xs:!min-w-40 xs:w-32 xs:!text-3xl md:!min-w-[185px] md:!text-4xl; } -.hstc-text{ - @apply lg:text-xl text-xs w-1/2 mx-auto text-center text-wrap lg:mt-6 lg:mb-10 mt-5 mb-5 font-sf-pro-display + +.hero-description { + @apply lg:text-xl text-xs w-1/2 mx-auto text-center lg:mt-6 lg:mb-10 mt-5 mb-5 font-sf-pro-display; } -.hstc-btn{ - @apply text-5xl font-semibold mt-4 border-4 border-white py-3 px-12 bg-btnLight rounded-full + +.hero-button { + @apply text-5xl font-semibold mt-4 border-4 border-white py-3 px-12 bg-btnLight rounded-full; } -.hs-falling-astro{ - @apply z-20 lg:w-[30vw] w-[60vw] my-12 +.astronaut-animation { + @apply z-20 lg:w-[30vw] w-[60vw] my-12; } -.hs-text-cont2{ - @apply flex flex-col items-center my-4 text-white z-20 + +.additional-text-section { + @apply flex flex-col items-center my-4 text-white z-20; +} + +.additional-text-title { + @apply text-6xl font-semibold font-coin mb-7 text-center; +} + +.additional-text-description { + @apply text-xl text-center mt-4 mb-7 font-sf-pro-display; +} + +.hero-title-main { + background: linear-gradient(90deg, #FFFFFF 0%, #999999 100%); + background-clip: text; + -webkit-background-clip: text; + color: transparent; } -.hstc2-title{ - @apply text-6xl font-semibold font-coin mb-7 text-center + +.hero-title-sub { + background: linear-gradient(90deg, #FFFFFF 0%, #999999 100%); + background-clip: text; + -webkit-background-clip: text; + color: transparent; } -.hstc2-text{ - @apply text-xl text-center mt-4 mb-7 font-sf-pro-display -} \ No newline at end of file diff --git a/src/StarDustAdventures_frontend/src/components/landing/loreStoryline/Lore.jsx b/src/StarDustAdventures_frontend/src/components/landing/loreStoryline/Lore.jsx index 3df8b18..1e5a714 100644 --- a/src/StarDustAdventures_frontend/src/components/landing/loreStoryline/Lore.jsx +++ b/src/StarDustAdventures_frontend/src/components/landing/loreStoryline/Lore.jsx @@ -1,52 +1,151 @@ -import React from 'react' -import './lore.css' -import { loreText } from '../../../constants/text' +import React, { useEffect } from 'react'; +import './lore.css'; +import { loreText } from '../../../constants/text'; +import gsap from 'gsap'; +import { ScrollTrigger } from 'gsap/ScrollTrigger'; + +gsap.registerPlugin(ScrollTrigger); const Lore = () => { + + useEffect(() => { + const applyAnimations = () => { + if (window.innerWidth <= 768) { + + + gsap.fromTo('.ls-title, .ls-text', + { opacity: 1, y: 0 }, + { + scrollTrigger: { + trigger: '.ls-rotating-astro', + start: 'top-=100 top', + end: '+=200', + pin: '.ls-title, .ls-text', + pinSpacing: false, + scrub: true, + } + } + ); + + + gsap.fromTo('.ls-rotating-astro', + { opacity: 1, scale: 1 }, + { + scrollTrigger: { + trigger: '.lsm-first', + start: 'top center-=100', + end: '+=300', + pin: '.ls-rotating-astro', + pinSpacing: false, + scrub: true, + } + } + ); + + const sections = gsap.utils.toArray('.lsm-text-item'); + + sections.forEach((section, index) => { + + + gsap.fromTo(section, + { opacity: 0, y: 100 }, + { + opacity: 1, + y: 0, + scrollTrigger: { + trigger: section, + start: 'top 80%', + end: 'bottom 60%', + toggleActions: 'play none none none', + scrub: true, + } + } + ); + + + gsap.to('.ls-rotating-astro', { + opacity: 0.2, + scrollTrigger: { + trigger: section, + start: 'top 80%', + end: 'bottom 60%', + scrub: true, + } + }); + + + if (index > 1) { + gsap.to(sections[index - 2], { + opacity: 0, + y: -100, + scrollTrigger: { + trigger: section, + start: 'top 80%', + end: 'top 60%', + scrub: true, + } + }); + } + }); + } + }; + + applyAnimations(); + window.addEventListener('resize', applyAnimations); + + return () => { + window.removeEventListener('resize', applyAnimations); + }; + }, []); + return (
-

- {loreText.title} -

-

- {loreText.subHeading} -

- -
+

+ {loreText.title} +

+

+ {loreText.subHeading} +

+ +
astronaut adventure -
-
-

{loreText.data[0].title}

-
{loreText.data[0].text}
-
-
-
-
-

{loreText.data[1].title}

-
{loreText.data[1].text}
-
-
-

{loreText.data[2].title}

-
{loreText.data[2].text}
-
-
-
-
-

{loreText.data[3].title}

-
{loreText.data[3].text}
-
-
-

{loreText.data[4].title}

-
{loreText.data[4].text}
-
-
+ +
+
+

{loreText.data[0].title}

+
{loreText.data[0].text}
+
+
+ +
+
+

{loreText.data[1].title}

+
{loreText.data[1].text}
+
+
+

{loreText.data[2].title}

+
{loreText.data[2].text}
+
+
+ +
+
+

{loreText.data[3].title}

+
{loreText.data[3].text}
+
+
+

{loreText.data[4].title}

+
{loreText.data[4].text}
+
+
+
- ) + ); } -export default Lore \ No newline at end of file +export default Lore; diff --git a/src/StarDustAdventures_frontend/src/components/landing/loreStoryline/lore.css b/src/StarDustAdventures_frontend/src/components/landing/loreStoryline/lore.css index 8476911..b56732a 100644 --- a/src/StarDustAdventures_frontend/src/components/landing/loreStoryline/lore.css +++ b/src/StarDustAdventures_frontend/src/components/landing/loreStoryline/lore.css @@ -25,9 +25,53 @@ .lsm-text-item{ @apply flex flex-col items-center w-[300px] } -.lsm-ti-title{ - @apply mb-3 text-3xl font-semibold text-center +.lsm-ti-title { + @apply mb-3 text-3xl font-semibold text-center text-white; } + .lsm-ti-text{ - @apply w-[250px] text-center font-medium text-lg -} \ No newline at end of file + @apply w-[250px] text-center font-medium text-lg text-white; +} + +@media screen and (max-width: 800px) { + .lsm-first , .lsm-second , .lsm-third { + display: block ; + position: sticky; + margin-left : auto ; + margin-right: auto ; + width: 100%; + + } + .ls-main{ + display: grid; + + } + .ls-main img{ + /* position: absolute ; */ + width: 100vw; + + } + .lsm-text-item{ + margin-top: 100px; + } + .lore-sec{ + text-align: center; + transform: translateY(-60px) + } + .ls-text{ + width: 80%; + } + .lsm-second{ + margin-bottom: 100px; + } + .lsm-side-right{ + transform: translateX(20px); + } + .lsm-side-left{ + transform: translateX(-1px); + } + .left-blue-pattern{ + display:none; +} + +} diff --git a/src/StarDustAdventures_frontend/src/components/re-usables/Button/Button.tsx b/src/StarDustAdventures_frontend/src/components/re-usables/Button/Button.tsx index b1edf85..28c79a4 100644 --- a/src/StarDustAdventures_frontend/src/components/re-usables/Button/Button.tsx +++ b/src/StarDustAdventures_frontend/src/components/re-usables/Button/Button.tsx @@ -1,66 +1,78 @@ -/* - * Button Component for StarDust Adventures - * This is a re-usable button component for the StarDust Adventures project - * The button component has the following props: - * variant: 'primary' | 'secondary' - * size: 'sm' | 'md' | 'lg' | 'xl' | 'xxl' - * className: string - * The button component is styled using Tailwind CSS - * The button component is exported as default - * clsx is used to combine multiple classes - * @param {ButtonProps} props - * @returns {JSX.Element} - * @author @ArjunQBTech - * @version 1.0 -*/ - import clsx from "clsx"; import './index.css'; interface ButtonProps extends React.ButtonHTMLAttributes { - variant?: 'primary' | 'secondary'; - size?: 'sm' | 'md' | 'lg' | 'xl' | 'xxl'; - className?: string; + variant?: 'primary' | 'secondary'; + size?: 'sm' | 'md' | 'lg' | 'xl' | 'xxl'; + className?: string; } +/** + * Reusable Button Component for StarDust Adventures + * + * This is a reusable button component that can be used across the StarDust Adventures project. + * It accepts various props to control its styling and behavior. + * The button uses Tailwind CSS classes, and `clsx` is used to combine the styles dynamically. + * + * @component + * @param {ButtonProps} props - The props for the Button component + * @param {'primary' | 'secondary'} [props.variant='primary'] - Defines the button variant (color scheme) + * @param {'sm' | 'md' | 'lg' | 'xl' | 'xxl'} [props.size='md'] - Defines the size of the button + * @param {string} [props.className] - Additional class names to apply custom styles + * @param {React.ReactNode} props.children - The content to be rendered inside the button + * @returns {JSX.Element} The rendered button component + * + * @example + * // Example usage of the Button component + * + * + * @example + * + * + * @version 1.0 + * @author @ArjunQBTech + */ +export default function Button({ + children, + variant = 'primary', + size = 'md', + className = '', + ...props +}: ButtonProps): JSX.Element { -export default function Button( - { - children, - variant = 'primary', - size = 'md', - className = '', - ...props - }: ButtonProps) { + const sizes = { + 'sm': 'text-sm min-w-[100px] text-[20px]', + 'md': 'min-w-[185px] text-[30px]', + 'lg': 'text-base px-6 py-2', + 'xl': 'text-lg px-8 py-3', + 'xxl': 'text-xl px-10 py-3' + }; - const sizes = { - 'sm': 'text-sm min-w-[100px] text-[20px]', - 'md': 'min-w-[185px] text-[30px]', - 'lg': 'text-base px-6 py-2', - 'xl' : 'text-lg px-8 py-3', - 'xxl' : 'text-xl px-10 py-3' - } + const vSpacing = { + 'sm': 'my-1', + 'md': 'my-2', + 'lg': 'my-3', + 'xl': 'my-4', + 'xxl': 'my-5' + }; - const vSpacing = { - 'sm': 'my-1', - 'md': 'my-2', - 'lg': 'my-3', - 'xl': 'my-4', - 'xxl': 'my-5' - } - - return ( - - ) -} \ No newline at end of file + return ( + + ); +} diff --git a/src/StarDustAdventures_frontend/src/index.css b/src/StarDustAdventures_frontend/src/index.css index 9d0ba16..61b4033 100644 --- a/src/StarDustAdventures_frontend/src/index.css +++ b/src/StarDustAdventures_frontend/src/index.css @@ -22,13 +22,14 @@ html{ scroll-behavior: smooth; + scrollbar-width: none; } body { overflow-x: hidden; min-height: 100vh; font-family: 'SF-Pro-Display', sans-serif; -} + } .app{ @apply min-h-screen bg-red-200 } @@ -37,4 +38,4 @@ body { } .overlay-black{ @apply z-10 w-screen h-[100%] bg-[rgb(0,0,0,0.65)] absolute top-0 min-h-screen -} \ No newline at end of file +} diff --git a/src/StarDustAdventures_frontend/src/pages/Landing.jsx b/src/StarDustAdventures_frontend/src/pages/Landing.jsx index 299ba66..da61ebc 100644 --- a/src/StarDustAdventures_frontend/src/pages/Landing.jsx +++ b/src/StarDustAdventures_frontend/src/pages/Landing.jsx @@ -1,38 +1,65 @@ -import React, { useEffect, useState } from 'react' -import '../components/landing/landing.css' -import Hero from '../components/landing/hero/Hero' -import Footer from '../components/landing/footer' -import GamePlayMechanics from '../components/landing/gamePlayMechanics' -import GameConcept from '../components/landing/gameConcept/GameConcept' -import Lore from '../components/landing/loreStoryline/Lore' -import GradientCover from '../components/landing/GradientCover' -import GameConceptM from '../components/landing-mobile/gameConcept/GameConceptM' - -const PatternCover = () => { - return( +import React, { lazy, Suspense, useEffect, useState } from 'react'; +import '../components/landing/landing.css'; +import Hero from '../components/landing/hero/Hero'; +import Footer from '../components/landing/footer'; +import GameConcept from '../components/landing/gameConcept/GameConcept'; +import Lore from '../components/landing/loreStoryline/Lore'; +import GradientCover from '../components/landing/GradientCover'; +import GameConceptM from '../components/landing-mobile/gameConcept/GameConceptM'; + +const GamePlayMechanics = lazy(() => import('../components/landing/gamePlayMechanics')); +const MobileGameplayView = lazy(() => import('../components/landing-mobile/gameplayMechanics')); + +/** + * PatternCover component dynamically renders gameplay mechanics based on screen width, + * displaying a mobile or desktop view inside a gradient cover. It also includes the Lore component. + * + * @returns {JSX.Element} The PatternCover component wrapped in a GradientCover with dynamic content. + */ +const PatternCover = ()=> { + const [width, setWidth] = useState(window.innerWidth); + + useEffect(() => { + const handleResize = () => setWidth(window.innerWidth); + window.addEventListener('resize', handleResize); + + return () => window.removeEventListener('resize', handleResize); + }, []); + + return ( - - + Loading...

}> + {width > 768 ? : } + +
- ) -} + ); +}; + +/** + * Landing component renders the main landing page, including the Hero, Game Concept, and Footer sections. + * It dynamically switches between mobile and desktop versions of the GameConcept component based on screen width. + * + * @returns {JSX.Element} The complete landing page layout. + */ +const Landing = ()=>{ + const [width, setWidth] = useState(window.innerWidth); -const Landing = () => { - const [width,setWidth]=useState(window.innerWidth) + useEffect(() => { + const handleResize = () => setWidth(window.innerWidth); + window.addEventListener('resize', handleResize); - useEffect(()=>{ - window.addEventListener("resize", ()=>setWidth(window.innerWidth)); - return () => window.removeEventListener("resize", ()=>setWidth(window.innerWidth)); - },[]) + return () => window.removeEventListener('resize', handleResize); + }, []); return ( -
- - {width>1024?:} - -