feat(carousel): add clickable carousel indicators
This commit is contained in:
139
components/ServiceCarousel.tsx
Normal file
139
components/ServiceCarousel.tsx
Normal file
@ -0,0 +1,139 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import {
|
||||
Carousel,
|
||||
CarouselContent,
|
||||
CarouselItem,
|
||||
} from "@/components/ui/carousel";
|
||||
import CurrentSlide from "@/hooks/CurrentSlide";
|
||||
import Image from "next/image";
|
||||
|
||||
export default function CarouselWrapper() {
|
||||
const serviceCarousel = [
|
||||
{
|
||||
id: 0,
|
||||
content: (
|
||||
<>
|
||||
<section className="lg:flex lg:flex-row-reverse lg:justify-between space-y-6 lg:items-center">
|
||||
<div className="lg:w-1/2">
|
||||
<Image
|
||||
src={"/images/campaign-strategy.png"}
|
||||
width={2464}
|
||||
height={1672}
|
||||
alt="campaign-strategy"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-4 lg:w-1/3 lg:space-y-12">
|
||||
<p className="px-6 py-2 lg:px-9 lg:py-4 lg:text-xl text-[#7B2E45] font-lato border-2 border-[#7B2E45] rounded-full w-fit">
|
||||
01
|
||||
</p>
|
||||
<h2 className="text-4xl lg:text-7xl text-white font-lato">
|
||||
Campaign Strategy
|
||||
</h2>
|
||||
<p className="text-lg lg:text-2xl font-lato text-white/60">
|
||||
Comprehensive planning from research to execution, crafted to
|
||||
win hearts and minds.
|
||||
</p>
|
||||
<div className="flex gap-4 w-full">
|
||||
<div className="bg-[#7B2E45]/80 rounded-full w-1/4 h-1 lg:w-[60px]" />
|
||||
<div className="bg-[#7B2E45]/65 rounded-full w-1/5 h-1 lg:w-[50px]" />
|
||||
<div className="bg-[#7B2E45]/50 rounded-full w-1/6 h-1 lg:w-[40px]" />
|
||||
<div className="bg-[#7B2E45]/35 rounded-full w-1/7 h-1 lg:w-[30px]" />
|
||||
<div className="bg-[#7B2E45]/20 rounded-full w-1/8 h-1 lg:w-[20px]" />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 1,
|
||||
content: (
|
||||
<>
|
||||
<section className="lg:flex lg:flex-row-reverse lg:justify-between space-y-6 lg:items-center">
|
||||
<div className="lg:w-1/2">
|
||||
<Image
|
||||
src={"/images/media-production.png"}
|
||||
width={2464}
|
||||
height={1672}
|
||||
alt="media-production"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-4 lg:w-1/3 lg:space-y-12">
|
||||
<p className="px-6 py-2 lg:px-9 lg:py-4 lg:text-xl text-[#7B2E45] font-lato border-2 border-[#7B2E45] rounded-full w-fit">
|
||||
02
|
||||
</p>
|
||||
<h2 className="text-4xl lg:text-7xl text-white font-lato">
|
||||
Media Production
|
||||
</h2>
|
||||
<p className="text-lg font-lato text-white/60">
|
||||
Cinematic storytelling through video, photography, and
|
||||
multimedia content that captivates.
|
||||
</p>
|
||||
<div className="flex gap-4 w-full">
|
||||
<div className="bg-[#7B2E45]/80 rounded-full w-1/4 h-1 lg:w-[60px]" />
|
||||
<div className="bg-[#7B2E45]/65 rounded-full w-1/5 h-1 lg:w-[50px]" />
|
||||
<div className="bg-[#7B2E45]/50 rounded-full w-1/6 h-1 lg:w-[40px]" />
|
||||
<div className="bg-[#7B2E45]/35 rounded-full w-1/7 h-1 lg:w-[30px]" />
|
||||
<div className="bg-[#7B2E45]/20 rounded-full w-1/8 h-1 lg:w-[20px]" />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
content: (
|
||||
<>
|
||||
<section className="lg:flex lg:flex-row-reverse lg:justify-between space-y-6 lg:items-center">
|
||||
<div className="lg:w-1/2">
|
||||
<Image
|
||||
src={"/images/research.png"}
|
||||
width={2464}
|
||||
height={1672}
|
||||
alt="research"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-4 lg:w-1/3 lg:space-y-12">
|
||||
<p className="px-6 py-2 lg:px-9 lg:py-4 lg:text-xl text-[#7B2E45] font-lato border-2 border-[#7B2E45] rounded-full w-fit">
|
||||
03
|
||||
</p>
|
||||
<h2 className="text-4xl lg:text-7xl text-white font-lato">
|
||||
Research & Analytics
|
||||
</h2>
|
||||
<p className="text-lg font-lato text-white/60">
|
||||
Data-driven insights that inform every decision and optimize
|
||||
every outcome
|
||||
</p>
|
||||
<div className="flex gap-4 w-full">
|
||||
<div className="bg-[#7B2E45]/80 rounded-full w-1/4 h-1 lg:w-[60px]" />
|
||||
<div className="bg-[#7B2E45]/65 rounded-full w-1/5 h-1 lg:w-[50px]" />
|
||||
<div className="bg-[#7B2E45]/50 rounded-full w-1/6 h-1 lg:w-[40px]" />
|
||||
<div className="bg-[#7B2E45]/35 rounded-full w-1/7 h-1 lg:w-[30px]" />
|
||||
<div className="bg-[#7B2E45]/20 rounded-full w-1/8 h-1 lg:w-[20px]" />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</>
|
||||
),
|
||||
},
|
||||
];
|
||||
const [api, setApi] = useState<any>();
|
||||
|
||||
return (
|
||||
<>
|
||||
<Carousel setApi={setApi} className="w-full h-fit">
|
||||
<CarouselContent>
|
||||
{serviceCarousel.map(({ id, content }) => (
|
||||
<CarouselItem key={id}>{content}</CarouselItem>
|
||||
))}
|
||||
</CarouselContent>
|
||||
</Carousel>
|
||||
|
||||
{/* All slide reading logic happens inside this component */}
|
||||
<CurrentSlide api={api} />
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user