Bob AI: For the image on the hero section, have it switch in between
This commit is contained in:
@@ -16,53 +16,89 @@ const IMAGES = [
|
||||
|
||||
export default function HeroSection(): React.JSX.Element {
|
||||
const [currentImageIndex, setCurrentImageIndex] = useState(0);
|
||||
const [isLoading, setIsLoading] = useState(true);
|
||||
const [currentImage, setCurrentImage] = useState(IMAGES[0]);
|
||||
const [progress, setProgress] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => {
|
||||
setIsLoading(true);
|
||||
setCurrentImageIndex((prevIndex) => (prevIndex + 1) % IMAGES.length);
|
||||
}, 5000); // Change image every 5 seconds
|
||||
const duration = 5000; // 5 seconds per image
|
||||
const interval = 50; // update progress every 50ms
|
||||
const step = (interval / duration) * 100;
|
||||
|
||||
return () => clearInterval(interval);
|
||||
const timer = setInterval(() => {
|
||||
setProgress((prev) => {
|
||||
if (prev >= 100) {
|
||||
setCurrentImageIndex((prevIndex) => (prevIndex + 1) % IMAGES.length);
|
||||
return 0;
|
||||
}
|
||||
return prev + step;
|
||||
});
|
||||
}, interval);
|
||||
|
||||
return () => clearInterval(timer);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const image = new Image();
|
||||
image.src = IMAGES[currentImageIndex];
|
||||
image.onload = () => {
|
||||
setCurrentImage(IMAGES[currentImageIndex]);
|
||||
setIsLoading(false);
|
||||
};
|
||||
image.onerror = () => {
|
||||
console.error("Failed to load image:", IMAGES[currentImageIndex]);
|
||||
setIsLoading(false);
|
||||
};
|
||||
}, [currentImageIndex]);
|
||||
|
||||
return (
|
||||
<div id="hero" data-section="hero" className="relative">
|
||||
{isLoading && (
|
||||
<div className="absolute inset-0 flex items-center justify-center bg-background/80 z-10">
|
||||
<div className="animate-spin rounded-full h-12 w-12 border-t-2 border-b-2 border-foreground"></div>
|
||||
<div id="hero" data-webild-section="hero" className="relative w-full pt-24 pb-12 px-6">
|
||||
<div className="max-w-6xl mx-auto mb-12">
|
||||
<h1 className="text-6xl md:text-8xl font-bold tracking-tight mb-8 text-center">
|
||||
Innovate Marketing
|
||||
</h1>
|
||||
|
||||
<div className="flex flex-col md:flex-row justify-end items-end gap-6">
|
||||
<div className="max-w-md text-right">
|
||||
<p className="text-base md:text-lg text-muted-foreground mb-6">
|
||||
Your Vision, Amplified. We craft data-driven strategies and compelling narratives to elevate your brand and drive measurable results. Let's grow together.
|
||||
</p>
|
||||
<div className="flex items-center justify-end gap-4">
|
||||
<a href="#services" className="inline-flex items-center justify-center h-10 px-4 py-2 bg-primary text-primary-foreground hover:bg-primary/90 rounded-full font-medium transition-colors">
|
||||
Our Services
|
||||
</a>
|
||||
<a href="#contact" className="inline-flex items-center justify-center h-10 px-4 py-2 bg-secondary text-secondary-foreground hover:bg-secondary/80 rounded-full font-medium transition-colors">
|
||||
Contact Us
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<SectionErrorBoundary name="hero">
|
||||
<HeroBillboardBrand
|
||||
brand="Innovate Marketing"
|
||||
description="Your Vision, Amplified. We craft data-driven strategies and compelling narratives to elevate your brand and drive measurable results. Let's grow together."
|
||||
primaryButton={{
|
||||
text: "Our Services",
|
||||
href: "#services",
|
||||
}}
|
||||
secondaryButton={{
|
||||
text: "Contact Us",
|
||||
href: "#contact",
|
||||
}}
|
||||
imageSrc={currentImage}
|
||||
/>
|
||||
</SectionErrorBoundary>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="w-full max-w-6xl mx-auto relative rounded-3xl overflow-hidden aspect-[16/9] md:aspect-[21/9] shadow-2xl bg-muted">
|
||||
{IMAGES.map((src, index) => (
|
||||
<div
|
||||
key={src}
|
||||
className={`absolute inset-0 transition-opacity duration-1000 ease-in-out ${
|
||||
index === currentImageIndex ? 'opacity-100 z-10' : 'opacity-0 z-0'
|
||||
}`}
|
||||
>
|
||||
<img
|
||||
src={src}
|
||||
alt={`Slide ${index + 1}`}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
|
||||
{/* Progress Bars Overlay */}
|
||||
<div className="absolute bottom-6 left-0 right-0 z-20 flex justify-center gap-3 px-6">
|
||||
{IMAGES.map((_, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="h-1.5 w-16 sm:w-24 bg-white/30 rounded-full overflow-hidden backdrop-blur-sm cursor-pointer"
|
||||
onClick={() => {
|
||||
setCurrentImageIndex(index);
|
||||
setProgress(0);
|
||||
}}
|
||||
>
|
||||
<div
|
||||
className="h-full bg-white transition-all duration-75 ease-linear"
|
||||
style={{
|
||||
width: index === currentImageIndex
|
||||
? `${progress}%`
|
||||
: index < currentImageIndex ? '100%' : '0%'
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user