Untitled
unknown
plain_text
10 months ago
4.4 kB
17
Indexable
// components/hero-designs/ModernHero.tsx
import { motion } from "framer-motion";
import { ChevronDown } from "lucide-react";
import { ClientConfig } from "@/lib/client-config";
import { getR2ImageUrl } from "@/lib/r2";
interface ModernHeroProps {
config: ClientConfig;
}
export function ModernHero({ config }: ModernHeroProps) {
const heroConfig = config.welcomeHero || {};
const images = heroConfig.images || [config.highlightImage];
const mainImage = images[0];
const imageUrl = mainImage.startsWith('http')
? mainImage
: getR2ImageUrl(config.id, mainImage.split('/').pop() || '');
const overlayOpacity = heroConfig.overlayOpacity ?? 0.3;
const textColor = heroConfig.textColor === 'dark' ? 'text-gray-800' : 'text-white';
// Split title into words for animation
const titleWords = config.title.split(' ');
return (
<div className="relative h-screen w-full overflow-hidden">
{/* Background Image */}
<div className="absolute inset-0">
<img
src={imageUrl}
alt={config.title}
className="h-full w-full object-cover"
/>
<div
className="absolute inset-0 bg-gradient-to-b from-black/70 via-black/40 to-black/70"
style={{ opacity: overlayOpacity }}
/>
</div>
{/* Content */}
<div className="relative z-10 flex h-full flex-col items-center justify-center px-4 text-center">
{heroConfig.showLogo && heroConfig.logoUrl && (
<motion.img
src={heroConfig.logoUrl}
alt="Logo"
className="mb-8 h-16 w-auto"
initial={{ opacity: 0, y: -20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.8, delay: 0.2 }}
/>
)}
{/* Animated Title Words */}
<div className="mb-4 flex max-w-4xl flex-wrap justify-center gap-x-3 gap-y-2">
{titleWords.map((word, index) => (
<motion.span
key={index}
className={`${textColor} text-4xl font-bold sm:text-5xl md:text-6xl lg:text-7xl`}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: 0.3 + index * 0.1 }}
>
{word}
</motion.span>
))}
</div>
{/* Animated Subtitle with Reveal Effect */}
{heroConfig.subtitle && (
<div className="relative mt-6 overflow-hidden">
<motion.div
className="relative overflow-hidden"
initial={{ width: 0 }}
animate={{ width: "100%" }}
transition={{ duration: 1.2, delay: 0.6 + titleWords.length * 0.1 }}
>
<motion.p
className={`${textColor} max-w-xl text-lg sm:text-xl px-3`}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.5, delay: 0.8 + titleWords.length * 0.1 }}
>
{heroConfig.subtitle}
</motion.p>
</motion.div>
</div>
)}
{/* Animated Date */}
<motion.div
className={`${textColor} mt-8 text-lg sm:text-xl`}
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: 1 + titleWords.length * 0.1 }}
>
{config.date}
</motion.div>
</div>
{/* Gradient Overlay at Bottom */}
<div className="absolute bottom-0 left-0 right-0 h-32 bg-gradient-to-t from-black/40 to-transparent"></div>
{/* Scroll Indicator */}
{(heroConfig.scrollIndicator ?? true) && (
<motion.div
className="absolute bottom-8 left-0 right-0 flex justify-center"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{
duration: 0.8,
delay: 1.2 + titleWords.length * 0.1,
repeat: Infinity,
repeatType: "reverse",
repeatDelay: 0.5
}}
>
<ChevronDown className={`${textColor} h-8 w-8`} />
</motion.div>
)}
</div>
);
}Editor is loading...
Leave a Comment