314 lines
12 KiB
TypeScript
314 lines
12 KiB
TypeScript
import React, { useState, useEffect, useCallback } from 'react';
|
|
import { ChevronLeft, ChevronRight } from 'lucide-react';
|
|
import { navigateTo } from './Router';
|
|
import svgPaths from "../imports/svg-i1joeov37f";
|
|
|
|
interface SlideData {
|
|
id: number;
|
|
title: string;
|
|
backgroundImage: string;
|
|
shortTitle: string;
|
|
ctaText: string;
|
|
}
|
|
|
|
export default function HeroSection() {
|
|
const [currentSlide, setCurrentSlide] = useState(0);
|
|
const [isAutoPlaying, setIsAutoPlaying] = useState(true);
|
|
const [progressValues, setProgressValues] = useState([0, 0, 0, 0, 0]);
|
|
|
|
const slides: SlideData[] = [
|
|
{
|
|
id: 1,
|
|
title: "Build Leaders Who Drive Business Growth",
|
|
backgroundImage: "https://images.unsplash.com/photo-1705234384669-c6d31c61b789?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w3Nzg4Nzd8MHwxfHNlYXJjaHwxfHxleGVjdXRpdmUlMjBsZWFkZXJzaGlwJTIwZGV2ZWxvcG1lbnQlMjB0cmFpbmluZ3xlbnwxfHx8fDE3NTY4MDcyNjJ8MA&ixlib=rb-4.1.0&q=80&w=1080&utm_source=figma&utm_medium=referral",
|
|
shortTitle: "Leadership Development Programs",
|
|
ctaText: "Explore Leadership Journeys"
|
|
},
|
|
{
|
|
id: 2,
|
|
title: "Strengthen the Backbone: Your Managers",
|
|
backgroundImage: "https://images.unsplash.com/photo-1565688527174-775059ac429c?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w3Nzg4Nzd8MHwxfHNlYXJjaHwxfHxtYW5hZ2VtZW50JTIwdGVhbSUyMGRpc2N1c3Npb24lMjBvZmZpY2V8ZW58MXx8fHwxNzU2ODA2ODg1fDA&ixlib=rb-4.1.0&q=80&w=1080&utm_source=figma&utm_medium=referral",
|
|
shortTitle: "Management Development Programs",
|
|
ctaText: "Strengthen your Managerial Calibre"
|
|
},
|
|
{
|
|
id: 3,
|
|
title: "Shape Cultures That Accelerate Performance",
|
|
backgroundImage: "https://images.unsplash.com/photo-1531535807748-218331acbcb4?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w3Nzg4Nzd8MHwxfHNlYXJjaHwxfHxjb3Jwb3JhdGUlMjBjdWx0dXJlJTIwdGVhbSUyMGNvbGxhYm9yYXRpb258ZW58MXx8fHwxNzU2ODA2ODg5fDA&ixlib=rb-4.1.0&q=80&w=1080&utm_source=figma&utm_medium=referral",
|
|
shortTitle: "Culture & Competence Consulting",
|
|
ctaText: "Learn how we facilitate Change"
|
|
},
|
|
{
|
|
id: 4,
|
|
title: "Unlock Leadership Potential",
|
|
backgroundImage: "https://images.unsplash.com/photo-1714974528833-a10e19a8f951?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w3Nzg4Nzd8MHwxfHNlYXJjaHwxfHxleGVjdXRpdmUlMjBjb2FjaGluZyUyMG1lbnRvciUyMGNvbnZlcnNhdGlvbnxlbnwxfHx8fDE3NTY4MDY4OTR8MA&ixlib=rb-4.1.0&q=80&w=1080&utm_source=figma&utm_medium=referral",
|
|
shortTitle: "Coaching & Mentoring",
|
|
ctaText: "Start a Coaching Conversation"
|
|
},
|
|
{
|
|
id: 5,
|
|
title: "Know Your Leaders. Strengthen Your Pipeline.",
|
|
backgroundImage: "https://images.unsplash.com/photo-1697059361419-349e924ed363?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=M3w3Nzg4Nzd8MHwxfHNlYXJjaHwxfHxidXNpbmVzcyUyMGxlYWRlcnMlMjBzdHJhdGVneSUyMG1lZXRpbmd8ZW58MXx8fHwxNzU2ODA3Mjc0fDA&ixlib=rb-4.1.0&q=80&w=1080&utm_source=figma&utm_medium=referral",
|
|
shortTitle: "Assessments & Leadership Pipeline",
|
|
ctaText: "Discover Our Assessment Solutions"
|
|
}
|
|
];
|
|
|
|
const totalSlides = slides.length;
|
|
const slideDuration = 5000; // 5 seconds per slide
|
|
|
|
// Auto-advance slides
|
|
useEffect(() => {
|
|
if (!isAutoPlaying) return;
|
|
|
|
const interval = setInterval(() => {
|
|
setCurrentSlide((prev) => (prev + 1) % totalSlides);
|
|
}, slideDuration);
|
|
|
|
return () => clearInterval(interval);
|
|
}, [isAutoPlaying, totalSlides]);
|
|
|
|
// Progress bar animation
|
|
useEffect(() => {
|
|
if (!isAutoPlaying) return;
|
|
|
|
const interval = setInterval(() => {
|
|
setProgressValues(prev => {
|
|
const newProgress = [...prev];
|
|
newProgress[currentSlide] = Math.min(newProgress[currentSlide] + (100 / (slideDuration / 100)), 100);
|
|
// Reset progress when slide changes
|
|
if (newProgress[currentSlide] >= 100) {
|
|
newProgress[currentSlide] = 0;
|
|
// Reset other slides
|
|
newProgress.forEach((_, index) => {
|
|
if (index !== currentSlide) {
|
|
newProgress[index] = 0;
|
|
}
|
|
});
|
|
}
|
|
return newProgress;
|
|
});
|
|
}, 100);
|
|
|
|
return () => clearInterval(interval);
|
|
}, [currentSlide, isAutoPlaying]);
|
|
|
|
// Reset progress when manually changing slides
|
|
useEffect(() => {
|
|
setProgressValues(prev => {
|
|
const newProgress = [0, 0, 0, 0, 0];
|
|
newProgress[currentSlide] = 0;
|
|
return newProgress;
|
|
});
|
|
}, [currentSlide]);
|
|
|
|
const goToSlide = useCallback((slideIndex: number) => {
|
|
if (slideIndex !== currentSlide) {
|
|
setCurrentSlide(slideIndex);
|
|
setIsAutoPlaying(false);
|
|
// Resume auto-play after manual interaction
|
|
setTimeout(() => setIsAutoPlaying(true), 3000);
|
|
}
|
|
}, [currentSlide]);
|
|
|
|
const nextSlide = useCallback(() => {
|
|
const next = (currentSlide + 1) % totalSlides;
|
|
goToSlide(next);
|
|
}, [currentSlide, totalSlides, goToSlide]);
|
|
|
|
const prevSlide = useCallback(() => {
|
|
const prev = (currentSlide - 1 + totalSlides) % totalSlides;
|
|
goToSlide(prev);
|
|
}, [currentSlide, totalSlides, goToSlide]);
|
|
|
|
// Pause auto-play on hover
|
|
const handleMouseEnter = () => setIsAutoPlaying(false);
|
|
const handleMouseLeave = () => setIsAutoPlaying(true);
|
|
|
|
return (
|
|
<section
|
|
className="hero-section"
|
|
onMouseEnter={handleMouseEnter}
|
|
onMouseLeave={handleMouseLeave}
|
|
>
|
|
{/* Background Slides */}
|
|
{slides.map((slide, index) => (
|
|
<div
|
|
key={slide.id}
|
|
className={`hero-slide ${index === currentSlide ? 'active' : ''}`}
|
|
style={{
|
|
backgroundImage: `url('${slide.backgroundImage}')`
|
|
}}
|
|
>
|
|
<div className="hero-overlay" />
|
|
</div>
|
|
))}
|
|
|
|
{/* Hero Content */}
|
|
<div className="hero-content">
|
|
<div className="hero-text-section">
|
|
{/* Title */}
|
|
<h1 className="hero-title" style={{ whiteSpace: 'pre-line' }}>
|
|
{slides[currentSlide].title}
|
|
</h1>
|
|
|
|
{/* Dynamic CTA Button - Enhanced with Proper Navigation */}
|
|
<button
|
|
className="hero-slide-button group box-border content-stretch flex flex-row gap-2.5 items-center justify-start p-0 relative cursor-pointer overflow-hidden"
|
|
style={{
|
|
background: 'transparent',
|
|
border: 'none'
|
|
}}
|
|
onClick={() => {
|
|
console.log('Hero button clicked - navigating to contact page');
|
|
navigateTo('/contact?topic=leadership-pipeline');
|
|
}}
|
|
aria-label={slides[currentSlide].ctaText}
|
|
>
|
|
{/* Icon Container with Slide Animation */}
|
|
<div className="relative shrink-0 size-[50px] overflow-hidden">
|
|
{/* Background Rectangle - Consistent Blue Color */}
|
|
<div className="absolute inset-0 bg-[#04045B]" />
|
|
|
|
{/* Icon Layer - Sliding Animation */}
|
|
<div className="icon-layer absolute inset-0 w-full h-full">
|
|
{/* Primary Arrow - Slides out diagonally up-right */}
|
|
<div className="icon absolute inset-0 flex items-center justify-center transition-all duration-300 ease-in-out group-hover:translate-x-6 group-hover:-translate-y-6 group-hover:opacity-0">
|
|
<svg
|
|
className="block w-full h-full"
|
|
fill="none"
|
|
preserveAspectRatio="none"
|
|
viewBox="0 0 50 50"
|
|
>
|
|
<g clipPath="url(#clip0_95_1043_primary)">
|
|
<path d={svgPaths.p5b8d700} fill="white" />
|
|
<path d={svgPaths.p30b71a00} fill="white" />
|
|
</g>
|
|
<defs>
|
|
<clipPath id="clip0_95_1043_primary">
|
|
<rect fill="white" height="50" width="50" />
|
|
</clipPath>
|
|
</defs>
|
|
</svg>
|
|
</div>
|
|
|
|
{/* Secondary Arrow - Slides in from bottom-left */}
|
|
<div className="icon absolute inset-0 flex items-center justify-center opacity-0 -translate-x-6 translate-y-6 transition-all duration-300 ease-in-out group-hover:translate-x-0 group-hover:translate-y-0 group-hover:opacity-100">
|
|
<svg
|
|
className="block w-full h-full"
|
|
fill="none"
|
|
preserveAspectRatio="none"
|
|
viewBox="0 0 50 50"
|
|
>
|
|
<g clipPath="url(#clip0_95_1043_secondary)">
|
|
<path d={svgPaths.p5b8d700} fill="white" />
|
|
<path d={svgPaths.p30b71a00} fill="white" />
|
|
</g>
|
|
<defs>
|
|
<clipPath id="clip0_95_1043_secondary">
|
|
<rect fill="white" height="50" width="50" />
|
|
</clipPath>
|
|
</defs>
|
|
</svg>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Text Section with Vertical Slide Animation */}
|
|
<div className="text-layer relative shrink-0 overflow-hidden flex items-center" style={{
|
|
height: '28px',
|
|
fontFamily: 'Inter, sans-serif',
|
|
fontSize: '20px',
|
|
fontWeight: '400',
|
|
lineHeight: '28px',
|
|
whiteSpace: 'nowrap',
|
|
color: '#ffffff'
|
|
}}>
|
|
{/* Primary Text - Slides up and out */}
|
|
<div
|
|
className="text-element absolute inset-0 flex items-center justify-start transition-all duration-300 ease-in-out group-hover:-translate-y-full group-hover:opacity-0"
|
|
style={{
|
|
color: '#ffffff !important',
|
|
textShadow: '0 1px 2px rgba(0, 0, 0, 0.4)',
|
|
fontFamily: 'Inter, sans-serif',
|
|
fontSize: '20px',
|
|
fontWeight: '400',
|
|
lineHeight: '28px'
|
|
}}
|
|
>
|
|
{slides[currentSlide].ctaText}
|
|
</div>
|
|
|
|
{/* Secondary Text - Slides in from bottom */}
|
|
<div
|
|
className="text-element absolute inset-0 flex items-center justify-start translate-y-full opacity-0 transition-all duration-300 ease-in-out group-hover:translate-y-0 group-hover:opacity-100"
|
|
style={{
|
|
color: '#ffffff !important',
|
|
textShadow: '0 1px 2px rgba(0, 0, 0, 0.4)',
|
|
fontFamily: 'Inter, sans-serif',
|
|
fontSize: '20px',
|
|
fontWeight: '400',
|
|
lineHeight: '28px'
|
|
}}
|
|
>
|
|
{slides[currentSlide].ctaText}
|
|
</div>
|
|
</div>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
{/* Bottom Navigation */}
|
|
<div className="hero-navigation">
|
|
{/* Progress Section */}
|
|
<div className="hero-progress-container">
|
|
{slides.map((slide, index) => (
|
|
<div
|
|
key={slide.id}
|
|
className="hero-progress-item"
|
|
onClick={() => goToSlide(index)}
|
|
>
|
|
{/* Progress Bar */}
|
|
<div
|
|
className={`hero-progress-segment ${index === currentSlide ? 'active' : ''}`}
|
|
>
|
|
<div
|
|
className="hero-progress-fill"
|
|
style={{ width: index === currentSlide ? `${progressValues[index]}%` : '0%' }}
|
|
/>
|
|
</div>
|
|
|
|
{/* Progress Number */}
|
|
<div className={`hero-progress-number ${index === currentSlide ? 'active' : ''}`}>
|
|
{String(index + 1).padStart(2, '0')}
|
|
</div>
|
|
|
|
{/* Progress Text */}
|
|
<div className={`hero-progress-text ${index === currentSlide ? 'active' : ''}`}>
|
|
{slide.shortTitle}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
|
|
{/* Navigation Arrows */}
|
|
<div className="hero-controls">
|
|
<button
|
|
className="hero-nav-button"
|
|
onClick={prevSlide}
|
|
aria-label="Previous slide"
|
|
>
|
|
<ChevronLeft className="w-5 h-5" />
|
|
</button>
|
|
<button
|
|
className="hero-nav-button"
|
|
onClick={nextSlide}
|
|
aria-label="Next slide"
|
|
>
|
|
<ChevronRight className="w-5 h-5" />
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
);
|
|
} |