diff --git a/.eslintrc.json b/.eslintrc.json index c4ccd59..0a1c582 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -19,11 +19,12 @@ "plugins": ["react", "react-hooks"], "rules": { "react/react-in-jsx-scope": "off", - "no-unused-vars": "warn" + "no-unused-vars": "warn", + "react/prop-types": "off" }, "settings": { "react": { "version": "detect" } } -} \ No newline at end of file +} diff --git a/eslint.config.js b/eslint.config.js index 8cd6f98..69a8612 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -38,6 +38,7 @@ export default [ 'warn', { allowConstantExport: true }, ], + 'react/prop-types': 'off', }, }, ]; diff --git a/index.html b/index.html index 3ea656a..9396a8d 100644 --- a/index.html +++ b/index.html @@ -2,9 +2,12 @@ - + + + + - Project Athena + OpenCode
diff --git a/package.json b/package.json index e98b9a5..b27a52a 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,9 @@ "@babel/core": "^7.0.0", "@emotion/react": "^11.14.0", "@emotion/styled": "^11.14.0", + "@gsap/react": "^2.1.1", + "gsap": "^3.12.5", + "lenis": "^1.1.18", "lucide-react": "^0.468.0", "react": "^19.0.0", "react-dom": "^19.0.0", diff --git a/src/App.jsx b/src/App.jsx index dd9d4d0..71378ad 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,12 +1,28 @@ -function App() { +import Lenis from 'lenis'; +import Gallery from './components/Gallery/Gallery'; +import MeetTheTeam from './components/MeetTheTeam/MeetTheTeam'; +import Hero from './components/Hero/hero.jsx'; +import Navbar from './components/Navbar/navbar.jsx'; +import Footer from './components/Footer/footer.jsx'; +import AboutUs from './components/AboutUs/AboutUs.jsx'; + +// Initialize Lenis +// eslint-disable-next-line no-unused-vars +const lenis = new Lenis({ + autoRaf: true, +}); + +const App = () => { return ( -
- OpenCode - +
+ + + + + +
); -} +}; export default App; diff --git a/src/Playground.jsx b/src/Playground.jsx index 0da69d9..71378ad 100644 --- a/src/Playground.jsx +++ b/src/Playground.jsx @@ -1,15 +1,28 @@ -import Hero from './components/hero.jsx'; -import Navbar from './components/navbar.jsx'; -import Footer from './components/footer.jsx'; +import Lenis from 'lenis'; +import Gallery from './components/Gallery/Gallery'; +import MeetTheTeam from './components/MeetTheTeam/MeetTheTeam'; +import Hero from './components/Hero/hero.jsx'; +import Navbar from './components/Navbar/navbar.jsx'; +import Footer from './components/Footer/footer.jsx'; +import AboutUs from './components/AboutUs/AboutUs.jsx'; -const Playground = () => { +// Initialize Lenis +// eslint-disable-next-line no-unused-vars +const lenis = new Lenis({ + autoRaf: true, +}); + +const App = () => { return (
+ + +
); }; -export default Playground; +export default App; diff --git a/src/components/AboutUs/AboutUs.jsx b/src/components/AboutUs/AboutUs.jsx new file mode 100644 index 0000000..18ea470 --- /dev/null +++ b/src/components/AboutUs/AboutUs.jsx @@ -0,0 +1,58 @@ +import Heading from '../shared/Heading'; +import AnimatedButton from './AnimatedButton'; +import TextWithModal from './TextWithModal'; + +const topics = ['AI/ML', 'Web Dev', 'App Dev', 'Cybersecurity', 'Open-Source']; + +const AboutUs = () => { + return ( +
+ +
+ + + + +
+ + About us. + + +
+
+ {topics.map((item, idx) => { + return ( +
+ +
+ ); + })} +
+
+
+ ); +}; + +export default AboutUs; diff --git a/src/components/AboutUs/AnimatedButton.jsx b/src/components/AboutUs/AnimatedButton.jsx new file mode 100644 index 0000000..7541d0e --- /dev/null +++ b/src/components/AboutUs/AnimatedButton.jsx @@ -0,0 +1,52 @@ +import { useGSAP } from '@gsap/react'; +import gsap from 'gsap'; + +const AnimatedButton = ({ text }) => { + gsap.registerPlugin(useGSAP); + useGSAP(() => { + gsap.to('#rotate-this', { + rotate: '720deg', + duration: 4, + repeat: -1, + ease: 'linear', + }); + gsap.to('#rotate-that', { + rotate: '720deg', + duration: 4, + repeat: -1, + ease: 'linear', + }); + }); + return ( +
+
+
+
+
+
+
+ {text} +
+
+
+
+
+ ); +}; + +export default AnimatedButton; diff --git a/src/components/AboutUs/TextWithModal.jsx b/src/components/AboutUs/TextWithModal.jsx new file mode 100644 index 0000000..99a0b9e --- /dev/null +++ b/src/components/AboutUs/TextWithModal.jsx @@ -0,0 +1,53 @@ +import { useState, useEffect } from 'react'; + +const TextWithModal = () => { + const [isTruncated, setIsTruncated] = useState(false); + + const fullText = `At our core, we are a passionate collective of innovators, + developers, and tech enthusiasts dedicated to pushing the boundaries of + technology. Our mission is to create cutting-edge solutions that solve + real-world problems and drive digital transformation. With a diverse team + of experts spanning multiple domains, we blend creativity, technical + expertise, and a relentless pursuit of excellence to deliver impactful + technological solutions.`; + + useEffect(() => { + const checkTextTruncation = () => { + // Adjust this breakpoint as needed + setIsTruncated(window.innerWidth < 768); + }; + + // Check on mount + checkTextTruncation(); + + // Add event listener for window resize + window.addEventListener('resize', checkTextTruncation); + + // Cleanup listener + return () => { + window.removeEventListener('resize', checkTextTruncation); + }; + }, []); + + // Function to truncate text + const getTruncatedText = () => { + return fullText.slice(0, 201) + '...'; + }; + + const handleCLick = () => { + console.log('clicked!'); + }; + + return ( +
+
+ {isTruncated ? <>{getTruncatedText()} : fullText} +
+
+ ); +}; + +export default TextWithModal; diff --git a/src/components/ComingSoon/ComingSoon.jsx b/src/components/ComingSoon/ComingSoon.jsx new file mode 100644 index 0000000..72a51ed --- /dev/null +++ b/src/components/ComingSoon/ComingSoon.jsx @@ -0,0 +1,35 @@ +import Navbar from '../Navbar/navbar'; + +export default function ComingSoon() { + return ( +
+ +
+

+ COMING SOON +

+
+ + + + + + +
+
+
+ ); +} diff --git a/src/components/footer.jsx b/src/components/Footer/footer.jsx similarity index 62% rename from src/components/footer.jsx rename to src/components/Footer/footer.jsx index d8cfaf9..e07ea11 100644 --- a/src/components/footer.jsx +++ b/src/components/Footer/footer.jsx @@ -13,7 +13,7 @@ export default function Footer() {
Join us ↗ @@ -24,31 +24,39 @@ export default function Footer() {
- + OPENCODE
-

- Sed ut perspiciatis unde omnis iste natus error sit voluptatem - accusantium doloremquez laudantium, totam rem aperiam, eaque ipsa - quae andSed ut perspiciatis unde omnis iste natus error sit - voluptatem accusantium doloremque laudantium, totam rem aperiam, - eaque ipsa quae and -

@@ -56,16 +64,28 @@ export default function Footer() { Architected with ❤️ by OpenCode Team

- + - + - + - +
diff --git a/src/components/Gallery/Gallery.jsx b/src/components/Gallery/Gallery.jsx new file mode 100644 index 0000000..c553797 --- /dev/null +++ b/src/components/Gallery/Gallery.jsx @@ -0,0 +1,146 @@ +import Photo from './Photo'; +import { useState } from 'react'; +import gsap from 'gsap'; +import { useGSAP } from '@gsap/react'; +import { ScrollTrigger } from 'gsap/ScrollTrigger'; +import Heading from '../shared/Heading'; + +const Gallery = () => { + // eslint-disable-next-line no-unused-vars + const [meetCoolPeople, setMeetCoolPeople] = useState(() => [ + { + src: 'https://res.cloudinary.com/dqcrkrtyr/image/upload/v1734165998/image_8197_bqosvx.png', + rotateFrom: gsap.utils.random(-10, 10), + rotateTo: gsap.utils.random(-10, 10), + }, + { + src: 'https://res.cloudinary.com/dqcrkrtyr/image/upload/v1734165997/image_8195_df6msw.png', + rotateFrom: gsap.utils.random(-10, 10), + rotateTo: gsap.utils.random(-10, 10), + }, + { + src: 'https://res.cloudinary.com/dqcrkrtyr/image/upload/v1734165998/image_8050_ptbz0x.png', + rotateFrom: gsap.utils.random(-10, 10), + rotateTo: gsap.utils.random(-10, 10), + }, + { + src: 'https://res.cloudinary.com/dqcrkrtyr/image/upload/v1734165998/image_8048_l6c63p.png', + rotateFrom: gsap.utils.random(-10, 10), + rotateTo: gsap.utils.random(-10, 10), + }, + { + src: 'https://res.cloudinary.com/dqcrkrtyr/image/upload/v1734165998/image_8054_liggqt.png', + rotateFrom: gsap.utils.random(-10, 10), + rotateTo: gsap.utils.random(-10, 10), + }, + { + src: 'https://res.cloudinary.com/dqcrkrtyr/image/upload/v1734165997/image_8049_uje361.png', + rotateFrom: gsap.utils.random(-10, 10), + rotateTo: gsap.utils.random(-10, 10), + }, + { + src: 'https://res.cloudinary.com/dqcrkrtyr/image/upload/v1734165997/image_8046_lsrwjc.png', + rotateFrom: gsap.utils.random(-10, 10), + rotateTo: gsap.utils.random(-10, 10), + }, + ]); + + gsap.registerPlugin(useGSAP); + gsap.registerPlugin(ScrollTrigger); + console.log('width = ', window.innerWidth, '\nheight = ', window.innerHeight); + + const stConfig = { + scrollTrigger: { + trigger: '#meet-cool-people', + scroller: 'body', + start: 'top top', + end: 'top -400%', + scrub: 2, + pin: true, + }, + }; + + useGSAP(() => { + const mcpTL = gsap.timeline(stConfig); + mcpTL.to( + '#meet-cool-people-photos', + { + x: '-133.33%', + }, + 0 + ); + mcpTL.to( + '#meet-cool-people', + { + backgroundColor: '#1a1a1a', + }, + 0 + ); + }); + + return ( +
+ + + + + Meet our Cool People + +
+
+ {meetCoolPeople.map((item, idx) => { + return ( + + ); + })} +
+
+ {meetCoolPeople + .slice(0, Math.ceil(meetCoolPeople.length / 2)) + .map((item, idx) => ( + + ))} +
+
+ {meetCoolPeople + .slice(Math.ceil(meetCoolPeople.length / 2)) + .map((item, idx) => ( + + ))} +
+
+
+ ); +}; + +export default Gallery; diff --git a/src/components/Gallery/Photo.jsx b/src/components/Gallery/Photo.jsx new file mode 100644 index 0000000..c614cf3 --- /dev/null +++ b/src/components/Gallery/Photo.jsx @@ -0,0 +1,35 @@ +import { useRef } from 'react'; +import gsap from 'gsap'; +import { useGSAP } from '@gsap/react'; + +const Photo = ({ rotateFrom, rotateTo, src }) => { + const photoRef = useRef(null); + + gsap.registerPlugin(useGSAP); + useGSAP(() => { + gsap.to(photoRef.current, { + rotate: `${rotateTo}deg`, + yoyo: true, + repeat: -1, + ease: 'steps(3)', + duration: 2, + }); + }, [rotateTo]); + + return ( +
+
+
+ hello +
+
+
+
+ ); +}; + +export default Photo; diff --git a/src/components/Gallery/assets/centerLight.svg b/src/components/Gallery/assets/centerLight.svg new file mode 100644 index 0000000..c97e7f5 --- /dev/null +++ b/src/components/Gallery/assets/centerLight.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/components/Gallery/assets/leftLight.svg b/src/components/Gallery/assets/leftLight.svg new file mode 100644 index 0000000..4ce7780 --- /dev/null +++ b/src/components/Gallery/assets/leftLight.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/components/Gallery/assets/rightLight.svg b/src/components/Gallery/assets/rightLight.svg new file mode 100644 index 0000000..29e9c07 --- /dev/null +++ b/src/components/Gallery/assets/rightLight.svg @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + + + diff --git a/src/components/Hero/hero.jsx b/src/components/Hero/hero.jsx new file mode 100644 index 0000000..5cdf3e2 --- /dev/null +++ b/src/components/Hero/hero.jsx @@ -0,0 +1,49 @@ +import Pulse from '../Pulse/Pulse'; + +export default function Home() { + return ( +
+ +
+
+ Opensource your imagination +
+

+ OPENCODE +

+

+ The{' '} + + Opensource + {' '} + and{' '} + + Cybersecurity + {' '} + community of NIT Rourkela +

+ +
+
+ ); +} diff --git a/src/components/MeetTheTeam/MeetTheTeam.jsx b/src/components/MeetTheTeam/MeetTheTeam.jsx new file mode 100644 index 0000000..26108e5 --- /dev/null +++ b/src/components/MeetTheTeam/MeetTheTeam.jsx @@ -0,0 +1,378 @@ +import Photo from './Photo'; +import gsap from 'gsap'; +import { useGSAP } from '@gsap/react'; +import { useEffect, useState } from 'react'; +import { ScrollTrigger } from 'gsap/ScrollTrigger'; +import Heading from '../shared/Heading'; + +const MeetTheTeam = () => { + const [orientation, setOrientation] = useState( + window.screen.orientation.type.split('-')[0] + ); + + useEffect(() => { + setOrientation(window.screen.orientation.type.split('-')[0]); + }, [setOrientation]); + + // eslint-disable-next-line no-unused-vars + const [meetTheTeam, setMeetTheTeam] = useState(() => [ + { + name: 'Suryakant Jena', + post: 'President', + photo: + 'https://res.cloudinary.com/dqcrkrtyr/image/upload/v1733908269/surya_v5ojeq.png', + rotateFrom: '0', + rotateTo: 'rotate-[-4.07deg]', + }, + { + name: 'Prapti P Pradhan', + post: 'Vice President', + photo: + 'https://res.cloudinary.com/dqcrkrtyr/image/upload/v1733908321/prapti_usrcux.png', + rotateFrom: '0', + rotateTo: 'rotate-[2.17deg]', + }, + { + name: 'Riya Pojage', + post: 'Community Manager', + photo: + 'https://res.cloudinary.com/dqcrkrtyr/image/upload/v1733908304/riya_pojage_kui6lj.png', + rotateFrom: '0', + rotateTo: 'rotate-0', + }, + { + name: 'Srishty Mangutte', + post: 'Tech Lead', + photo: + 'https://res.cloudinary.com/dqcrkrtyr/image/upload/v1733908286/sristy_dxorna.png', + rotateFrom: '0', + rotateTo: 'rotate-[-3.36deg]', + }, + ]); + gsap.registerPlugin(useGSAP); + gsap.registerPlugin(ScrollTrigger); + + const stConfig = { + trigger: '#meet-the-team', + scroller: 'body', + start: 'top top', + end: 'top -400%', + scrub: 2, + }; + + const setupConfig = { + scrollTrigger: { + ...stConfig, + pin: true, + }, + }; + + const baseConfig = { + scrollTrigger: { + ...stConfig, + }, + }; + + useGSAP(() => { + const photoTL = gsap.timeline(setupConfig); + photoTL + .from('#photo0', { + y: orientation == 'portrait' ? '80dvh' : '100%', + rotate: 0, + duration: 2, + delay: 1, + ease: 'power4.out', + }) + .from('#photo1', { + y: orientation == 'portrait' ? '80dvh' : '100%', + rotate: 0.56, + duration: 2, + ease: 'power4.out', + }) + .from('#photo2', { + y: orientation == 'portrait' ? '80dvh' : '100%', + rotate: -9.23, + duration: 2, + ease: 'power4.out', + }) + .from('#photo3', { + y: orientation == 'portrait' ? '80dvh' : '100%', + rotate: 3.93, + duration: 2, + ease: 'power4.out', + }); + }); + + useGSAP(() => { + const photoFadeTL = gsap.timeline(baseConfig); + photoFadeTL + .to('#photo0-film', { + opacity: 0.6, + duration: 2, + delay: 3, + ease: 'power4.out', + }) + .to('#photo1-film', { + opacity: 0.6, + duration: 2, + ease: 'power4.out', + }) + .to('#photo2-film', { + opacity: 0.6, + duration: 2, + ease: 'power4.out', + }); + }); + + useGSAP(() => { + const nameTL = gsap.timeline(baseConfig); + nameTL + .from('#name-0', { + y: '100%', + opacity: 0, + duration: 2, + delay: 1, + ease: 'power4.out', + }) + .from('#name-1', { + y: '100%', + opacity: 0, + duration: 2, + ease: 'power4.out', + }) + .from('#name-2', { + y: '100%', + opacity: 0, + duration: 2, + ease: 'power4.out', + }) + .from('#name-3', { + y: '100%', + opacity: 0, + duration: 2, + ease: 'power4.out', + }); + }); + + useGSAP(() => { + const nameFadeTL = gsap.timeline(baseConfig); + nameFadeTL + .to('#name-0', { + y: '-100%', + opacity: 0, + duration: 2, + delay: 3, + ease: 'power4.out', + }) + .to('#name-1', { + y: '-100%', + opacity: 0, + duration: 2, + ease: 'power4.out', + }) + .to('#name-2', { + y: '-100%', + opacity: 0, + duration: 2, + ease: 'power4.out', + }); + }); + + useGSAP(() => { + const postTL = gsap.timeline(baseConfig); + postTL + .from('#post-0', { + y: '100%', + opacity: 0, + duration: 2, + delay: 1, + ease: 'power4.out', + }) + .from('#post-1', { + y: '100%', + opacity: 0, + duration: 2, + ease: 'power4.out', + }) + .from('#post-2', { + y: '100%', + opacity: 0, + duration: 2, + ease: 'power4.out', + }) + .from('#post-3', { + y: '100%', + opacity: 0, + duration: 2, + ease: 'power4.out', + }); + }); + + useGSAP(() => { + const postFadeTL = gsap.timeline(baseConfig); + postFadeTL + .to('#post-0', { + y: '-100%', + opacity: 0, + duration: 2, + delay: 3, + ease: 'power4.out', + }) + .to('#post-1', { + y: '-100%', + opacity: 0, + duration: 2, + ease: 'power4.out', + }) + .to('#post-2', { + y: '-100%', + opacity: 0, + duration: 2, + ease: 'power4.out', + }); + }); + + return ( +
+ {/* background */} + + + + + +
+ {/* heading */} + + Meet The Team + + + {/* gallery section */} + +
+
+ ); +}; + +export default MeetTheTeam; diff --git a/src/components/MeetTheTeam/Photo.jsx b/src/components/MeetTheTeam/Photo.jsx new file mode 100644 index 0000000..912a40e --- /dev/null +++ b/src/components/MeetTheTeam/Photo.jsx @@ -0,0 +1,25 @@ +const Photo = ({ src, rotate, z, id }) => { + return ( +
+
+
+ +
+
+
+ ); +}; + +export default Photo; diff --git a/src/components/navbar.jsx b/src/components/Navbar/navbar.jsx similarity index 61% rename from src/components/navbar.jsx rename to src/components/Navbar/navbar.jsx index c0aacd2..141cf75 100644 --- a/src/components/navbar.jsx +++ b/src/components/Navbar/navbar.jsx @@ -5,10 +5,10 @@ export default function Navbar() { const [isOpen, setIsOpen] = React.useState(false); const navigationItems = [ - { href: '/about', label: 'About' }, - { href: '/events', label: 'Events' }, - { href: '/projects', label: 'Projects' }, - { href: '/team', label: 'Team' }, + { href: '/coming-soon', label: 'About' }, + { href: '/coming-soon', label: 'Events' }, + { href: '/coming-soon', label: 'Projects' }, + { href: '/coming-soon', label: 'Team' }, ]; return ( @@ -20,10 +20,10 @@ export default function Navbar() { onClick={() => setIsOpen(false)} /> -
-