Skip to content

Commit 3599c33

Browse files
Shadow-MMNShadow-MMNBenjtalkshow
authored
Feature/about us timeline (boundlessfi#174)
* feat: created the timeline section of the about page * fix: minor fix --------- Co-authored-by: Shadow-MMN <nnajimakuochukwu4@example.com> Co-authored-by: Nnaji Benjamin <60315147+Benjtalkshow@users.noreply.github.com>
1 parent 52cb88a commit 3599c33

23 files changed

Lines changed: 1110 additions & 6 deletions

app/(landing)/about/layout.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// components/DashboardLayout.tsx
2+
import BeamBackground from '@/components/landing-page/BeamBackground';
3+
import React, { ReactNode } from 'react';
4+
type AboutLayoutProps = {
5+
children: ReactNode;
6+
};
7+
8+
const AboutLayout = ({ children }: AboutLayoutProps) => {
9+
return (
10+
<section>
11+
<BeamBackground />
12+
{children}
13+
</section>
14+
);
15+
};
16+
17+
export default AboutLayout;

app/(landing)/about/page.tsx

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import React from 'react';
22
import { Metadata } from 'next';
33
import { generatePageMetadata } from '@/lib/metadata';
4+
5+
import Timeline from '@/components/landing-page/about/timeline/Timeline';
6+
import AboutLayout from './layout';
7+
48
import TestimonialsSection from '@/components/testimonials/TestimonialsSection';
59
import { testimonials } from '@/components/testimonials/data/testimonial';
610
import OurTeam from './OurTeam';
@@ -10,13 +14,19 @@ export const metadata: Metadata = generatePageMetadata('about');
1014

1115
const AboutPage = () => {
1216
return (
13-
<div className='relative z-10 space-y-[23px] md:space-y-[80px] max-w-[1300px] mx-auto'>
14-
<OurTeam />
15-
<Partners />
16-
<div className='text-white text-4xl font-bold text-center mt-10'>
17-
<TestimonialsSection testimonials={testimonials} />
17+
<AboutLayout>
18+
{/* Hero Section */}
19+
{/* Boundless Difference */}
20+
<Timeline />
21+
22+
<div className="relative z-10 space-y-[23px] md:space-y-[80px] max-w-[1300px] mx-auto">
23+
<OurTeam />
24+
<Partners />
25+
<div className="text-white text-4xl font-bold text-center mt-10">
26+
<TestimonialsSection testimonials={testimonials} />
27+
</div>
1828
</div>
19-
</div>
29+
</AboutLayout>
2030
);
2131
};
2232

app/globals.css

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,3 +368,36 @@ input[type='number'] {
368368
-webkit-background-clip: text;
369369
-webkit-text-fill-color: transparent;
370370
}
371+
372+
/* About Timeline Card's Background gradient for images */
373+
.my-gradient-box {
374+
background: radial-gradient(circle, #ffffff7a, #ffffff14);
375+
}
376+
377+
/* Background Images for the three Timeline Cards */
378+
.time-card-background-image-one {
379+
background-image: url('/landing/about/Abstract_01.png');
380+
}
381+
.time-card-background-image-two {
382+
background-image: url('/landing/about/Abstract_02.png');
383+
}
384+
.time-card-background-image-three {
385+
background-image: url('/landing/about/Abstract_03.png');
386+
}
387+
388+
.time-card-general-background-positioning {
389+
background-repeat: no-repeat;
390+
background-size: contain;
391+
background-position: bottom right;
392+
}
393+
@media (min-width: 768px) {
394+
.time-card-background-image-one {
395+
background-image: url('/landing/about/Abstract_01md.png');
396+
}
397+
.time-card-background-image-two {
398+
background-image: url('/landing/about/Abstract_02md.png');
399+
}
400+
.time-card-background-image-three {
401+
background-image: url('/landing/about/Abstract_03md.png');
402+
}
403+
}
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
'use client';
2+
import React, { useState } from 'react';
3+
import { aboutTimelineData } from '@/constants';
4+
import { motion } from 'framer-motion';
5+
import TimelineCard from './TimelineCard';
6+
import { ChevronLeft, ChevronRight } from 'lucide-react';
7+
import ProgressiveeBarSvg from './ProgressiveeBarSvg';
8+
9+
const ImageSlider = () => {
10+
const [currentIndex, setCurrentIndex] = useState(0);
11+
const totalItems = aboutTimelineData.length;
12+
13+
const next = () => {
14+
setCurrentIndex(prevIndex => (prevIndex + 1) % totalItems);
15+
};
16+
17+
const prev = () => {
18+
setCurrentIndex(prevIndex => (prevIndex - 1 + totalItems) % totalItems);
19+
};
20+
21+
const getPosition = (
22+
index: number
23+
): 'center' | 'left' | 'right' | 'hidden' => {
24+
const diff = (index - currentIndex + totalItems) % totalItems;
25+
26+
if (diff === 0) return 'center';
27+
if (diff === 1 || diff === totalItems - 1) {
28+
return diff === 1 ? 'right' : 'left';
29+
}
30+
return 'hidden';
31+
};
32+
33+
const imageVariants = {
34+
center: {
35+
x: '0%',
36+
scale: 1,
37+
zIndex: 5,
38+
opacity: 1,
39+
rotateY: 0,
40+
},
41+
left: {
42+
x: '-40%',
43+
scale: 0.8,
44+
zIndex: 2,
45+
opacity: 0.7,
46+
rotateY: 15,
47+
},
48+
right: {
49+
x: '40%',
50+
scale: 0.8,
51+
zIndex: 2,
52+
opacity: 0.7,
53+
rotateY: -15,
54+
},
55+
hidden: {
56+
x: '0%',
57+
scale: 0.5,
58+
zIndex: 1,
59+
opacity: 0,
60+
},
61+
};
62+
63+
return (
64+
<div className='flex relative min-h-[500px] max-w-[800px] mx-auto items-center'>
65+
<div className='relative w-full h-[400px]'>
66+
{aboutTimelineData.map((item, index) => {
67+
const position = getPosition(index);
68+
const { img, year, title, subTitle, backgroundImage } = item;
69+
return (
70+
<motion.div
71+
key={index}
72+
initial='center'
73+
animate={position}
74+
variants={imageVariants}
75+
transition={{
76+
duration: 0.6,
77+
ease: 'easeInOut',
78+
}}
79+
className='absolute inset-0 flex justify-center items-center'
80+
style={{
81+
width: '450px',
82+
left: '50%',
83+
marginLeft: '-200px',
84+
}}
85+
>
86+
<TimelineCard
87+
img={img}
88+
year={year}
89+
title={title}
90+
subTitle={subTitle}
91+
backgroundImage={backgroundImage}
92+
/>
93+
</motion.div>
94+
);
95+
})}
96+
</div>
97+
98+
{/* Left and Right button */}
99+
<button
100+
onClick={prev}
101+
className='absolute left-32 top-1/2 -translate-y-1/2 bg-gray-900/80 hover:bg-gray-800 rounded-full p-2 shadow-lg transition-colors z-10'
102+
>
103+
<ChevronLeft className='w-6 h-6 text-white' />
104+
</button>
105+
106+
<button
107+
onClick={next}
108+
className='absolute right-24 top-1/2 -translate-y-1/2 bg-gray-900/80 hover:bg-gray-800 rounded-full p-2 shadow-lg transition-colors z-10'
109+
>
110+
<ChevronRight className='w-6 h-6 text-white' />
111+
</button>
112+
113+
{/* Progress Bar and Number */}
114+
<div className='absolute bottom-0 left-1/2 -translate-x-1/2 flex items-center'>
115+
{aboutTimelineData.map((_, index) => (
116+
<div key={index} className='flex items-center'>
117+
<button
118+
onClick={() => setCurrentIndex(index)}
119+
className={`text-sm font-medium transition-colors ${
120+
index === currentIndex ? 'text-white' : 'text-gray-700/65'
121+
}`}
122+
>
123+
{String(index + 1).padStart(2, '0')}
124+
</button>
125+
126+
{index < aboutTimelineData.length - 1 && (
127+
<div className='mx-4'>
128+
<ProgressiveeBarSvg />
129+
</div>
130+
)}
131+
</div>
132+
))}
133+
</div>
134+
</div>
135+
);
136+
};
137+
138+
export default ImageSlider;

0 commit comments

Comments
 (0)