diff --git a/app/(landing)/about/layout.tsx b/app/(landing)/about/layout.tsx new file mode 100644 index 000000000..cdf88c395 --- /dev/null +++ b/app/(landing)/about/layout.tsx @@ -0,0 +1,17 @@ +// components/DashboardLayout.tsx +import BeamBackground from '@/components/landing-page/BeamBackground'; +import React, { ReactNode } from 'react'; +type AboutLayoutProps = { + children: ReactNode; +}; + +const AboutLayout = ({ children }: AboutLayoutProps) => { + return ( +
+ + {children} +
+ ); +}; + +export default AboutLayout; diff --git a/app/(landing)/about/page.tsx b/app/(landing)/about/page.tsx index c29498bbf..0ff1e782f 100644 --- a/app/(landing)/about/page.tsx +++ b/app/(landing)/about/page.tsx @@ -1,6 +1,10 @@ import React from 'react'; import { Metadata } from 'next'; import { generatePageMetadata } from '@/lib/metadata'; + +import Timeline from '@/components/landing-page/about/timeline/Timeline'; +import AboutLayout from './layout'; + import TestimonialsSection from '@/components/testimonials/TestimonialsSection'; import { testimonials } from '@/components/testimonials/data/testimonial'; import OurTeam from './OurTeam'; @@ -10,13 +14,19 @@ export const metadata: Metadata = generatePageMetadata('about'); const AboutPage = () => { return ( -
- - -
- + + {/* Hero Section */} + {/* Boundless Difference */} + + +
+ + +
+ +
-
+ ); }; diff --git a/app/globals.css b/app/globals.css index cb10f508f..581291a80 100644 --- a/app/globals.css +++ b/app/globals.css @@ -368,3 +368,36 @@ input[type='number'] { -webkit-background-clip: text; -webkit-text-fill-color: transparent; } + +/* About Timeline Card's Background gradient for images */ +.my-gradient-box { + background: radial-gradient(circle, #ffffff7a, #ffffff14); +} + +/* Background Images for the three Timeline Cards */ +.time-card-background-image-one { + background-image: url('/landing/about/Abstract_01.png'); +} +.time-card-background-image-two { + background-image: url('/landing/about/Abstract_02.png'); +} +.time-card-background-image-three { + background-image: url('/landing/about/Abstract_03.png'); +} + +.time-card-general-background-positioning { + background-repeat: no-repeat; + background-size: contain; + background-position: bottom right; +} +@media (min-width: 768px) { + .time-card-background-image-one { + background-image: url('/landing/about/Abstract_01md.png'); + } + .time-card-background-image-two { + background-image: url('/landing/about/Abstract_02md.png'); + } + .time-card-background-image-three { + background-image: url('/landing/about/Abstract_03md.png'); + } +} diff --git a/components/landing-page/about/timeline/ImageSlider.tsx b/components/landing-page/about/timeline/ImageSlider.tsx new file mode 100644 index 000000000..122c765f5 --- /dev/null +++ b/components/landing-page/about/timeline/ImageSlider.tsx @@ -0,0 +1,138 @@ +'use client'; +import React, { useState } from 'react'; +import { aboutTimelineData } from '@/constants'; +import { motion } from 'framer-motion'; +import TimelineCard from './TimelineCard'; +import { ChevronLeft, ChevronRight } from 'lucide-react'; +import ProgressiveeBarSvg from './ProgressiveeBarSvg'; + +const ImageSlider = () => { + const [currentIndex, setCurrentIndex] = useState(0); + const totalItems = aboutTimelineData.length; + + const next = () => { + setCurrentIndex(prevIndex => (prevIndex + 1) % totalItems); + }; + + const prev = () => { + setCurrentIndex(prevIndex => (prevIndex - 1 + totalItems) % totalItems); + }; + + const getPosition = ( + index: number + ): 'center' | 'left' | 'right' | 'hidden' => { + const diff = (index - currentIndex + totalItems) % totalItems; + + if (diff === 0) return 'center'; + if (diff === 1 || diff === totalItems - 1) { + return diff === 1 ? 'right' : 'left'; + } + return 'hidden'; + }; + + const imageVariants = { + center: { + x: '0%', + scale: 1, + zIndex: 5, + opacity: 1, + rotateY: 0, + }, + left: { + x: '-40%', + scale: 0.8, + zIndex: 2, + opacity: 0.7, + rotateY: 15, + }, + right: { + x: '40%', + scale: 0.8, + zIndex: 2, + opacity: 0.7, + rotateY: -15, + }, + hidden: { + x: '0%', + scale: 0.5, + zIndex: 1, + opacity: 0, + }, + }; + + return ( +
+
+ {aboutTimelineData.map((item, index) => { + const position = getPosition(index); + const { img, year, title, subTitle, backgroundImage } = item; + return ( + + + + ); + })} +
+ + {/* Left and Right button */} + + + + + {/* Progress Bar and Number */} +
+ {aboutTimelineData.map((_, index) => ( +
+ + + {index < aboutTimelineData.length - 1 && ( +
+ +
+ )} +
+ ))} +
+
+ ); +}; + +export default ImageSlider; diff --git a/components/landing-page/about/timeline/ProgressiveeBarSvg.tsx b/components/landing-page/about/timeline/ProgressiveeBarSvg.tsx new file mode 100644 index 000000000..446a75a3c --- /dev/null +++ b/components/landing-page/about/timeline/ProgressiveeBarSvg.tsx @@ -0,0 +1,268 @@ +import React from 'react'; + +const ProgressiveeBarSvg = () => { + return ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default ProgressiveeBarSvg; diff --git a/components/landing-page/about/timeline/Timeline.tsx b/components/landing-page/about/timeline/Timeline.tsx new file mode 100644 index 000000000..ff2915b67 --- /dev/null +++ b/components/landing-page/about/timeline/Timeline.tsx @@ -0,0 +1,97 @@ +'use client'; +import TimelineLayout from './TimelineLayout'; +import { aboutTimelineData } from '@/constants'; +import React, { useEffect, useRef } from 'react'; +import TimelineCard from './TimelineCard'; +import ImageSlider from './ImageSlider'; +import { gsap } from 'gsap'; +import TopRightSvg from './backgroundSvgs/TopRightSvg'; +import MiddleLeftSvg from './backgroundSvgs/MiddleLeftSvg'; +import MiddleRightSvg from './backgroundSvgs/MiddleRightSvg'; +import BottomLeftSvg from './backgroundSvgs/BottomLeftSvg'; + +const Timeline = () => { + const svgRefs = useRef<(SVGPathElement | null)[]>([]); + + useEffect(() => { + svgRefs.current.forEach((path, i) => { + if (path) { + const length = path.getTotalLength(); + + // set initial hidden state + gsap.set(path, { + strokeDasharray: length, + strokeDashoffset: length, + opacity: 0, + }); + + // continuous animation + gsap.to(path, { + strokeDashoffset: 0, + opacity: 1, + duration: 2, + ease: 'power2.inOut', + delay: 0.3 * i, // stagger by index + repeat: -1, // infinite loop + yoyo: true, // reverse back + }); + } + }); + }, []); + + return ( + + {/* Heading with Top Right SVG */} +
+
+

+ Timeline +

+

+ Our Journey +

+
+ + {/* Top Right SVG */} + +
+ + {/* Cards mobile */} +
+ {aboutTimelineData.map((item, index) => { + const { img, year, title, subTitle, backgroundImage } = item; + return ( + + ); + })} +
+ + {/* Carousel with Middle SVGs */} +
+
+ +
+ + {/* Left Middle SVG */} + + + {/* Right Middle SVG */} + +
+ + {/* Bottom SVG */} +
+ +
+
+ ); +}; + +export default Timeline; diff --git a/components/landing-page/about/timeline/TimelineCard.tsx b/components/landing-page/about/timeline/TimelineCard.tsx new file mode 100644 index 000000000..44dd2eb3d --- /dev/null +++ b/components/landing-page/about/timeline/TimelineCard.tsx @@ -0,0 +1,50 @@ +import Image from 'next/image'; +import React from 'react'; + +interface props { + img: string; + year: string; + title: string; + subTitle: string; + backgroundImage: string; +} + +const TimelineCard = ({ + img, + year, + title, + subTitle, + backgroundImage, +}: props) => { + return ( +
+
+
+ Yellow Bulb +
+ +

+ {year} +

+
+
+

+ {title} +

+

+ {subTitle} +

+
+
+ ); +}; + +export default TimelineCard; diff --git a/components/landing-page/about/timeline/TimelineLayout.tsx b/components/landing-page/about/timeline/TimelineLayout.tsx new file mode 100644 index 000000000..463180a7c --- /dev/null +++ b/components/landing-page/about/timeline/TimelineLayout.tsx @@ -0,0 +1,15 @@ +// components/DashboardLayout.tsx +import React, { ReactNode } from 'react'; +type TimelineLayoutProps = { + children: ReactNode; +}; + +const TimelineLayout = ({ children }: TimelineLayoutProps) => { + return ( +
+ {children} +
+ ); +}; + +export default TimelineLayout; diff --git a/components/landing-page/about/timeline/backgroundSvgs/BottomLeftSvg.tsx b/components/landing-page/about/timeline/backgroundSvgs/BottomLeftSvg.tsx new file mode 100644 index 000000000..27818e50d --- /dev/null +++ b/components/landing-page/about/timeline/backgroundSvgs/BottomLeftSvg.tsx @@ -0,0 +1,134 @@ +import React from 'react'; + +interface BottomLeftSvgProps { + svgRefs: React.MutableRefObject<(SVGPathElement | null)[]>; +} + +const BottomLeftSvg: React.FC = ({ svgRefs }) => { + return ( +
+ + { + svgRefs.current[5] = el; + }} + d='M376.5 1H331.641L288.749 39H203.752L171.03 68.5H7' + stroke='url(#paint0_linear_2191_14135)' + strokeOpacity='0.9' + strokeWidth='2' + strokeLinecap='round' + /> + + { + svgRefs.current[6] = el; + }} + d='M235.625 39H273.008' + stroke='url(#paint1_linear_2191_14135)' + strokeWidth='2' + strokeLinecap='round' + /> + + + { + svgRefs.current[7] = el; + }} + d='M7.39258 68H47.53' + stroke='url(#paint3_linear_2191_14135)' + strokeWidth='2' + strokeLinecap='round' + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ ); +}; + +export default BottomLeftSvg; diff --git a/components/landing-page/about/timeline/backgroundSvgs/MiddleLeftSvg.tsx b/components/landing-page/about/timeline/backgroundSvgs/MiddleLeftSvg.tsx new file mode 100644 index 000000000..70339c508 --- /dev/null +++ b/components/landing-page/about/timeline/backgroundSvgs/MiddleLeftSvg.tsx @@ -0,0 +1,47 @@ +import React from 'react'; + +interface MiddleLeftSvgProps { + svgRefs: React.MutableRefObject<(SVGPathElement | null)[]>; +} + +const MiddleLeftSvg: React.FC = ({ svgRefs }) => { + return ( +
+ + { + svgRefs.current[2] = el; + }} + d='M1 57H283.521L323 1H351' + stroke='url(#paint0_linear_2191_14143)' + strokeOpacity='0.9' + strokeWidth='2' + strokeLinecap='round' + /> + + + + + + + + + +
+ ); +}; + +export default MiddleLeftSvg; diff --git a/components/landing-page/about/timeline/backgroundSvgs/MiddleRightSvg.tsx b/components/landing-page/about/timeline/backgroundSvgs/MiddleRightSvg.tsx new file mode 100644 index 000000000..af5ff8991 --- /dev/null +++ b/components/landing-page/about/timeline/backgroundSvgs/MiddleRightSvg.tsx @@ -0,0 +1,76 @@ +import React from 'react'; + +interface MiddleRightSvgProps { + svgRefs: React.MutableRefObject<(SVGPathElement | null)[]>; +} + +const MiddleRightSvg: React.FC = ({ svgRefs }) => { + return ( +
+ + { + svgRefs.current[3] = el; + }} + d='M1 7H362.313' + stroke='#1F2D11' + strokeLinecap='round' + /> + + { + svgRefs.current[4] = el; + }} + d='M318.6 7H358.544' + stroke='url(#paint0_linear_2191_14144)' + strokeWidth='2' + strokeLinecap='round' + /> + + + + + + + + + + + + + + +
+ ); +}; + +export default MiddleRightSvg; diff --git a/components/landing-page/about/timeline/backgroundSvgs/TopRightSvg.tsx b/components/landing-page/about/timeline/backgroundSvgs/TopRightSvg.tsx new file mode 100644 index 000000000..19b9a0b0f --- /dev/null +++ b/components/landing-page/about/timeline/backgroundSvgs/TopRightSvg.tsx @@ -0,0 +1,90 @@ +import React from 'react'; + +interface TopRightSvgProps { + svgRefs: React.MutableRefObject<(SVGPathElement | null)[]>; +} + +const TopRightSvg: React.FC = ({ svgRefs }) => { + return ( +
+ + { + svgRefs.current[0] = el; + }} + d='M287.734 32H254.341L230.6 1L89.7574 1L45.1129 60.5H1' + stroke='url(#paint0_linear_2191_14130)' + strokeOpacity='0.9' + strokeWidth='2' + strokeLinecap='round' + /> + + { + svgRefs.current[1] = el; + }} + d='M260.894 32H287.999' + stroke='url(#paint1_linear_2191_14130)' + strokeWidth='2' + strokeLinecap='round' + /> + + + + + + + + + + + + + + + + + + + +
+ ); +}; + +export default TopRightSvg; diff --git a/constants/index.ts b/constants/index.ts new file mode 100644 index 000000000..ac9e57810 --- /dev/null +++ b/constants/index.ts @@ -0,0 +1,26 @@ +export const aboutTimelineData = [ + { + img: '/landing/about/emoji_objects.svg', + year: '2024', + title: 'Idea Inception', + subTitle: + 'Boundless was born from the need to validate and fund ideas fairly in Web3.', + backgroundImage: 'time-card-background-image-one', + }, + { + img: '/landing/about/rocket_launch.svg', + year: '2025', + title: 'MVP Launch on Stellar (Soroban)', + subTitle: + 'The first version of Boundless, enabling milestone-based crowdfunding, grants, and hackathons.', + backgroundImage: 'time-card-background-image-two', + }, + { + img: '/landing/about/globe_asia.svg', + year: 'Future', + title: 'Scaling Across Ecosystems', + subTitle: + 'Expanding Boundless beyond Stellar to support global innovators wherever they are.', + backgroundImage: 'time-card-background-image-three', + }, +]; diff --git a/public/landing/about/Abstract_01.png b/public/landing/about/Abstract_01.png new file mode 100644 index 000000000..ac1d230dc Binary files /dev/null and b/public/landing/about/Abstract_01.png differ diff --git a/public/landing/about/Abstract_01md.png b/public/landing/about/Abstract_01md.png new file mode 100644 index 000000000..221a6470b Binary files /dev/null and b/public/landing/about/Abstract_01md.png differ diff --git a/public/landing/about/Abstract_02.png b/public/landing/about/Abstract_02.png new file mode 100644 index 000000000..87f0ab2bf Binary files /dev/null and b/public/landing/about/Abstract_02.png differ diff --git a/public/landing/about/Abstract_02md.png b/public/landing/about/Abstract_02md.png new file mode 100644 index 000000000..f3816cac8 Binary files /dev/null and b/public/landing/about/Abstract_02md.png differ diff --git a/public/landing/about/Abstract_03.png b/public/landing/about/Abstract_03.png new file mode 100644 index 000000000..540abe55a Binary files /dev/null and b/public/landing/about/Abstract_03.png differ diff --git a/public/landing/about/Abstract_03md.png b/public/landing/about/Abstract_03md.png new file mode 100644 index 000000000..11edeac71 Binary files /dev/null and b/public/landing/about/Abstract_03md.png differ diff --git a/public/landing/about/emoji_objects.svg b/public/landing/about/emoji_objects.svg new file mode 100644 index 000000000..a2a443aaa --- /dev/null +++ b/public/landing/about/emoji_objects.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/landing/about/globe_asia.svg b/public/landing/about/globe_asia.svg new file mode 100644 index 000000000..30496683e --- /dev/null +++ b/public/landing/about/globe_asia.svg @@ -0,0 +1,3 @@ + + + diff --git a/public/landing/about/progressive-bar.svg b/public/landing/about/progressive-bar.svg new file mode 100644 index 000000000..24c894894 --- /dev/null +++ b/public/landing/about/progressive-bar.svg @@ -0,0 +1,94 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/public/landing/about/rocket_launch.svg b/public/landing/about/rocket_launch.svg new file mode 100644 index 000000000..74430fd3b --- /dev/null +++ b/public/landing/about/rocket_launch.svg @@ -0,0 +1,3 @@ + + +