File "Hero.tsx"
Full Path: /home/trinadezambia/public_html/student_panel/src/components/ui/pages/home/Hero.tsx
File size: 7.46 KB
MIME-type: text/x-java
Charset: utf-8
'use client';
import Container from '@/components/shared/container/Container';
import React, { useState, useEffect } from 'react';
import Image from 'next/image';
import {
Carousel,
CarouselContent,
CarouselItem,
type CarouselApi,
} from '@/components/ui/carousel';
import { ChevronLeft, ChevronRight } from 'lucide-react';
export default function Hero() {
const [currentSlide, setCurrentSlide] = useState(0);
const [api, setApi] = useState<CarouselApi | undefined>(undefined);
// Hero slide data
const heroSlides = [
{
id: 1,
badge: "Where Every Child's Journey Begins",
title: 'EMPOWERING YOUNG MINDS FOR A BRIGHTER FUTURE',
description:
'Empowering young minds through meaningful learning and lifelong values —from early years to graduation.',
image: '/assets/images/hero/slide1.png',
underline: '/assets/images/hero/underline.svg',
},
{
id: 2,
badge: 'Excellence in Education',
title: "BUILDING TOMORROW'S LEADERS TODAY",
description:
'Nurturing critical thinking, creativity, and character development to prepare students for success in an ever-changing world.',
image: '/assets/images/hero/slide1.png',
underline: '/assets/images/hero/underline.svg',
},
{
id: 3,
badge: 'Innovation in Learning',
title: 'INSPIRING LIFELONG LEARNING AND GROWTH',
description:
'Creating an environment where curiosity thrives, knowledge expands, and every student discovers their unique potential.',
image: '/assets/images/hero/slide1.png',
underline: '/assets/images/hero/underline.svg',
},
];
// Update current slide when carousel changes
useEffect(() => {
if (!api) return;
setCurrentSlide(api.selectedScrollSnap());
api.on('select', () => {
setCurrentSlide(api.selectedScrollSnap());
});
}, [api]);
// Autoplay functionality
useEffect(() => {
if (!api) return;
const autoplay = setInterval(() => {
api.scrollNext();
}, 10000); // 10 seconds between slides
return () => clearInterval(autoplay);
}, [api]);
return (
<section className="bg-[var(--light-primary-color)] py-8 md:py-16 relative">
<Container>
<Carousel
setApi={setApi}
className="w-full"
opts={{
align: 'start',
loop: true,
duration: 25, // Smooth transition duration
dragFree: true, // Enables smooth momentum scrolling
}}
>
<CarouselContent>
{heroSlides.map((slide) => (
<CarouselItem key={slide.id}>
<div className="grid grid-cols-12 gap-4 md:gap-8 items-center min-h-[400px] md:min-h-[500px]">
{/* Left side - Content */}
<div className="col-span-12 lg:col-span-6 flex flex-col justify-center space-y-3 md:space-y-4 order-2 lg:order-1 px-4 md:px-0">
{/* Badge */}
<div className="inline-block">
<span className="bg-[var(--tertiary-color)] text-white px-3 py-1.5 md:px-4 md:py-2 rounded-md text-xs md:text-sm font-medium">
{slide.badge}
</span>
</div>
{/* Main Title */}
<div className="space-y-4">
<h1 className="text-xl md:text-4xl lg:text-5xl xl:text-6xl font-bold text-black leading-tight">
{slide.title.split(' ').map((word, index) => (
<span key={index}>
{word === 'BRIGHTER' ? (
<span className="relative inline-block">
<span className="relative z-10">{word}</span>
<Image
src={slide.underline}
alt="underline"
width={0}
height={0}
className="hidden md:block absolute -bottom-12 left-0 z-0 w-full h-full object-cover"
/>
</span>
) : (
word
)}
{index < slide.title.split(' ').length - 1 && ' '}
</span>
))}
</h1>
</div>
{/* Description */}
<p className="text-base md:text-lg lg:text-xl font-normal text-gray-700 leading-relaxed max-w-2xl">
{slide.description}
</p>
</div>
{/* Right side - Image */}
<div className="col-span-12 lg:col-span-6 relative order-1 lg:order-2 px-4 md:px-0">
<div className="relative">
{/* Main image */}
<div className="relative z-10">
<Image
src={slide.image}
alt="Hero Image"
width={0}
height={0}
className="w-full h-[300px] sm:h-[400px] md:h-[650px] object-contain"
priority
/>
</div>
{/* Decorative elements */}
<div className="absolute top-4 right-4 md:top-10 md:right-10">
<div className="w-4 h-4 md:w-8 md:h-8 bg-[var(--secondary-color)] rounded-full opacity-60"></div>
</div>
<div className="absolute bottom-10 left-4 md:bottom-20 md:left-10">
<div className="w-3 h-3 md:w-6 md:h-6 bg-[var(--tertiary-color)] rounded-full opacity-60"></div>
</div>
</div>
</div>
</div>
</CarouselItem>
))}
</CarouselContent>
</Carousel>
{/* Pagination Dots */}
<div className="flex justify-center mt-6 md:mt-8 space-x-2">
{heroSlides.map((_, index) => (
<button
key={index}
onClick={() => api?.scrollTo(index)}
className={`h-3 rounded-full transition-all duration-300 ${
currentSlide === index
? 'w-[40px] bg-[var(--secondary-color)]'
: 'w-3 bg-gray-300 hover:bg-gray-400'
}`}
aria-label={`Go to slide ${index + 1}`}
/>
))}
</div>
</Container>
{/* Custom Navigation Buttons - Outside Container */}
<button
onClick={() => api?.scrollPrev()}
className="hidden lg:flex absolute left-16 top-1/2 cursor-pointer -translate-y-1/2 bg-[var(--secondary-color)] border-0 z-10 w-10 h-10 rounded-[4px] items-center justify-center transition-all duration-200 hover:scale-105"
aria-label="Previous slide"
>
<ChevronLeft className="h-4 w-4 text-white" />
</button>
<button
onClick={() => api?.scrollNext()}
className="hidden lg:flex absolute right-16 top-1/2 cursor-pointer -translate-y-1/2 bg-[var(--secondary-color)] border-0 z-10 w-10 h-10 rounded-[4px] items-center justify-center transition-all duration-200 hover:scale-105"
aria-label="Next slide"
>
<ChevronRight className="h-4 w-4 text-white" />
</button>
</section>
);
}