Skip to content

Commit 2c5520c

Browse files
Added feature(About page mission section) (boundlessfi#184)
Co-authored-by: Collins Ikechukwu <collinschristroa@gmail.com>
1 parent bb05e66 commit 2c5520c

20 files changed

Lines changed: 552 additions & 153 deletions

.env.example

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,4 @@ GOOGLE_CLIENT_SECRET=your_google_client_secret
5050
# Environment
5151
NODE_ENV=development
5252
# Options: development, production, test
53+

app/(landing)/about/page.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React from 'react';
22
import { Metadata } from 'next';
33
import { generatePageMetadata } from '@/lib/metadata';
4+
import Missionpage from '@/components/About-Mission/Missionpage';
45
import AboutUsDifferent from '@/components/landing-page/about/AboutUsDifferent';
56

67
import Timeline from '@/components/landing-page/about/timeline/Timeline';
@@ -16,6 +17,9 @@ export const metadata: Metadata = generatePageMetadata('about');
1617
const AboutPage = () => {
1718
return (
1819
<AboutLayout>
20+
<div className='text-white text-center'>
21+
<Missionpage />
22+
</div>
1923
{/* Hero Section */}
2024
{/* Boundless Difference */}
2125
<Timeline />
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
'use client';
2+
import GlowBackground from './missionbgassets/glow';
3+
import BackgroundOval from './missionbgassets/Backgroundline1';
4+
import BackgroundOval2 from './missionbgassets/Backgroundline2';
5+
import BackgroundOval3 from './missionbgassets/Backgroundline3';
6+
7+
export default function AboutUsMission() {
8+
return (
9+
<div className='relative flex justify-center items-center min-h-[60vh] sm:min-h-screen bg-black overflow-hidden w-full h-full max-w-6xl rounded-xl mx-auto'>
10+
<GlowBackground />
11+
<BackgroundOval className='absolute top-[34%] sm:top-[30%] md:top-[30%] left-0 w-full h-auto overflow-hidden' />
12+
<BackgroundOval2 className='absolute top-[35%] sm:top-[25%] md:top-[45%] lg:top-[45%] right-0 left-1/2 w-[100%] overflow-hidden' />
13+
<BackgroundOval3 className='absolute top-[50%] sm:top-[25%] md:top-[45%] left-1/2 right-0 w-[100%] overflow-hidden' />
14+
</div>
15+
);
16+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import React from 'react';
2+
import AboutUsMission from './Aboutmissionbg';
3+
import MissionText from './text';
4+
5+
export default function Missionpage() {
6+
return (
7+
<div className='relative min-h-screen bg-black text-white overflow-hidden'>
8+
<div className='absolute inset-0 z-0'>
9+
<AboutUsMission />
10+
</div>
11+
12+
<div className='relative z-10 flex items-center justify-center min-h-screen'>
13+
<MissionText />
14+
</div>
15+
</div>
16+
);
17+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
'use client';
2+
import React, { useRef } from 'react';
3+
import { useFadeGradient } from '@/hooks/use-fadegradient';
4+
5+
interface Props {
6+
className?: string;
7+
duration?: number;
8+
delay?: number;
9+
}
10+
11+
export default function AnimatedOval({
12+
className = '',
13+
duration = 1.5,
14+
delay = 0,
15+
}: Props) {
16+
const startRef = useRef<SVGStopElement | null>(null);
17+
const endRef = useRef<SVGStopElement | null>(null);
18+
19+
useFadeGradient([startRef, endRef], duration, delay);
20+
21+
return (
22+
<svg
23+
className={`absolute -translate-y-1/2 rotate-180 ${className}`}
24+
width='1224'
25+
height='339'
26+
viewBox='0 0 1224 339'
27+
fill='none'
28+
xmlns='http://www.w3.org/2000/svg'
29+
>
30+
<path
31+
d='M682 0.5C870.25 0.5 1040.66 48.3868 1163.98 125.782C1287.31 203.182 1363.5 310.045 1363.5 428C1363.5 545.955 1287.31 652.818 1163.98 730.218C1040.66 807.613 870.25 855.5 682 855.5C493.75 855.5 323.345 807.613 200.019 730.218C76.6857 652.818 0.5 545.955 0.5 428C0.5 310.045 76.6857 203.182 200.019 125.782C323.345 48.3868 493.75 0.5 682 0.5Z'
32+
stroke='url(#ovalGradient1)'
33+
strokeWidth='2.5'
34+
strokeLinecap='round'
35+
/>
36+
37+
<defs>
38+
<linearGradient
39+
id='ovalGradient1'
40+
x1='682'
41+
y1='0'
42+
x2='682'
43+
y2='856'
44+
gradientUnits='userSpaceOnUse'
45+
>
46+
<stop
47+
ref={startRef}
48+
offset='0%'
49+
stopColor='#D9D9D900'
50+
stopOpacity='0'
51+
/>
52+
<stop offset='80%' stopColor='#000000' stopOpacity='1' />
53+
<stop
54+
ref={endRef}
55+
offset='100%'
56+
stopColor='#D9D9D900'
57+
stopOpacity='0'
58+
/>
59+
</linearGradient>
60+
</defs>
61+
</svg>
62+
);
63+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
'use client';
2+
3+
import React, { useRef } from 'react';
4+
import { useFadeGradient } from '@/hooks/use-fadegradient';
5+
6+
interface Props {
7+
className?: string;
8+
duration?: number;
9+
delay?: number;
10+
}
11+
12+
export default function BackgroundOval2({
13+
className = '',
14+
duration = 1.5,
15+
delay = 0.2,
16+
}: Props) {
17+
const startRef = useRef<SVGStopElement | null>(null);
18+
const endRef = useRef<SVGStopElement | null>(null);
19+
20+
useFadeGradient([startRef, endRef], duration, delay);
21+
22+
return (
23+
<svg
24+
className={`absolute -translate-x-1/2 rotate-170 ${className}`}
25+
width='1240'
26+
height='467'
27+
viewBox='0 0 1240 467'
28+
fill='none'
29+
xmlns='http://www.w3.org/2000/svg'
30+
>
31+
<path
32+
d='M707 466.5C904.079 466.5 1082.48 412.629 1211.59 325.558C1340.71 238.484 1420.5 118.246 1420.5 -14.5C1420.5 -147.246 1340.71 -267.484 1211.59 -354.558C1082.48 -441.629 904.079 -495.5 707 -495.5C509.921 -495.5 331.521 -441.629 202.405 -354.558C73.2868 -267.484 -6.5 -147.246 -6.5 -14.5C-6.5 118.246 73.2868 238.484 202.405 325.558C331.521 412.629 509.921 466.5 707 466.5Z'
33+
stroke='url(#ovalGradient2)'
34+
strokeWidth='2.5'
35+
strokeLinecap='round'
36+
/>
37+
38+
<defs>
39+
<linearGradient
40+
id='ovalGradient2'
41+
x1='707'
42+
y1='467'
43+
x2='707'
44+
y2='-496'
45+
gradientUnits='userSpaceOnUse'
46+
>
47+
<stop
48+
ref={startRef}
49+
offset='0%'
50+
stopColor='#D9D9D900'
51+
stopOpacity='0'
52+
/>
53+
<stop offset='80%' stopColor='#000000' stopOpacity='1' />
54+
<stop
55+
ref={endRef}
56+
offset='100%'
57+
stopColor='#D9D9D900'
58+
stopOpacity='0'
59+
/>
60+
</linearGradient>
61+
</defs>
62+
</svg>
63+
);
64+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
'use client';
2+
3+
import React, { useRef } from 'react';
4+
import { useFadeGradient } from '@/hooks/use-fadegradient';
5+
6+
interface Props {
7+
className?: string;
8+
duration?: number;
9+
delay?: number;
10+
}
11+
12+
export default function BackgroundOval3({
13+
className = '',
14+
duration = 1.5,
15+
delay = 0.4, // stagger slightly after Oval 2
16+
}: Props) {
17+
const startRef = useRef<SVGStopElement | null>(null);
18+
const endRef = useRef<SVGStopElement | null>(null);
19+
20+
useFadeGradient([startRef, endRef], duration, delay);
21+
22+
return (
23+
<svg
24+
className={`absolute -translate-x-1/2 ${className}`}
25+
width='1240'
26+
height='353'
27+
viewBox='0 0 1240 353'
28+
fill='none'
29+
xmlns='http://www.w3.org/2000/svg'
30+
>
31+
<path
32+
d='M700.5 0.5C960.985 0.5 1196.79 49.1794 1367.45 127.862C1538.15 206.565 1643.5 315.191 1643.5 435C1643.5 554.809 1538.15 663.435 1367.45 742.138C1196.79 820.821 960.985 869.5 700.5 869.5C440.015 869.5 204.214 820.821 33.5537 742.138C-137.149 663.435 -242.5 554.809 -242.5 435C-242.5 315.191 -137.149 206.565 33.5537 127.862C204.214 49.1794 440.015 0.5 700.5 0.5Z'
33+
stroke='url(#ovalGradient3)'
34+
strokeWidth='2.5'
35+
strokeLinecap='round'
36+
/>
37+
38+
<defs>
39+
<linearGradient
40+
id='ovalGradient3'
41+
x1='700.5'
42+
y1='0'
43+
x2='700.5'
44+
y2='870'
45+
gradientUnits='userSpaceOnUse'
46+
>
47+
<stop
48+
ref={startRef}
49+
offset='0%'
50+
stopColor='#D9D9D900'
51+
stopOpacity='0'
52+
/>
53+
<stop offset='80%' stopColor='#000000' stopOpacity='1' />
54+
<stop
55+
ref={endRef}
56+
offset='100%'
57+
stopColor='#D9D9D900'
58+
stopOpacity='0'
59+
/>
60+
</linearGradient>
61+
</defs>
62+
</svg>
63+
);
64+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
'use client';
2+
3+
import Image from 'next/image';
4+
5+
export default function GlowBackground() {
6+
return (
7+
<>
8+
<div className='absolute top-0 left-0 w-40 h-36 md:w-120 md:h-140 sm:w-88 sm:h-84'>
9+
<Image
10+
src='/Top Glow.svg'
11+
alt='Top Glow'
12+
fill
13+
className='pointer-events-none select-none object-contain'
14+
priority
15+
/>
16+
</div>
17+
18+
<div className='absolute bottom-0 right-0 w-40 h-36 md:w-130 md:h-120 sm:w-58 sm:h-74'>
19+
<Image
20+
src='/Bottom Glow.svg'
21+
alt='Bottom Glow'
22+
fill
23+
className='pointer-events-none select-none object-cover'
24+
priority
25+
/>
26+
</div>
27+
</>
28+
);
29+
}

components/About-Mission/text.tsx

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
'use client';
2+
import { useEffect, useRef } from 'react';
3+
import { gsap } from 'gsap';
4+
5+
export default function MissionText() {
6+
const containerRef = useRef<HTMLHeadingElement>(null);
7+
8+
useEffect(() => {
9+
if (containerRef.current) {
10+
const chars = containerRef.current.querySelectorAll('.char');
11+
12+
gsap.fromTo(
13+
chars,
14+
{
15+
opacity: 1,
16+
y: 0,
17+
color: '#9CA3AF',
18+
textDecorationColor: 'transparent',
19+
},
20+
{
21+
opacity: 1,
22+
y: 0,
23+
color: '#ffffff',
24+
textDecorationColor: '#ffffff',
25+
duration: 0.4,
26+
ease: 'power3.out',
27+
stagger: 0.05,
28+
delay: 2,
29+
repeat: -1,
30+
repeatDelay: 2,
31+
}
32+
);
33+
}
34+
}, []);
35+
36+
const firstPhrase = 'Our mission is';
37+
const rest =
38+
'to empower anyone, anywhere, to transform bold ideas into impactful projects with transparency, community, and accountability at the core.';
39+
40+
return (
41+
<div className='flex flex-col justify-center items-center text-center px-6 max-w-[34rem] md:w-[80%] md:h-full sm:w-full sm:h-full sm:text-lg'>
42+
<h2
43+
ref={containerRef}
44+
className='text-xl sm:text-3xl md:text-2xl leading-relaxed'
45+
>
46+
<span className='text-white mr-1 underline underline-offset-4 decoration-white'>
47+
{firstPhrase}
48+
</span>
49+
{rest.split(' ').map((word, wordIndex) => (
50+
<span key={wordIndex} className='inline-block whitespace-nowrap'>
51+
{Array.from(word).map((char, charIndex) => (
52+
<span
53+
key={`${wordIndex}-${charIndex}`}
54+
className='char inline-block whitespace-pre text-gray-400 underline underline-offset-4 decoration-transparent'
55+
>
56+
{char}
57+
</span>
58+
))}
59+
<span className='char inline-block whitespace-pre text-gray-400'>
60+
&nbsp;
61+
</span>
62+
</span>
63+
))}
64+
</h2>
65+
</div>
66+
);
67+
}

components/layout/header.tsx

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,6 @@ const Header = () => {
107107
sheet.setOpen(o);
108108
}}
109109
/>
110-
111110
</motion.header>
112111
);
113112
};

0 commit comments

Comments
 (0)