Untitled
unknown
plain_text
14 days ago
7.9 kB
4
Indexable
"use client" import { motion } from "framer-motion" import type { ClientConfig } from "@/lib/client-config" import { getR2ImageUrl } from "@/lib/r2" import { ChevronDown, Heart } from "lucide-react" interface PortraitGalleryHeroProps { config: ClientConfig } export function PortraitGalleryHero({ config }: PortraitGalleryHeroProps) { const heroConfig = config.welcomeHero || {} const images = heroConfig.images || [config.highlightImage] // Limit to 3 images maximum const displayImages = images.slice(0, 3) // Determine layout based on number of images const layoutClass = displayImages.length === 1 ? "grid-cols-1" : displayImages.length === 2 ? "grid-cols-1 md:grid-cols-2" : "grid-cols-1 md:grid-cols-3" const overlayOpacity = heroConfig.overlayOpacity ?? 0.3 const textColor = heroConfig.textColor === "dark" ? "text-gray-800" : "text-white" // Get decorative elements configuration const decorativeElements = heroConfig.decorativeElements || {} const showCorners = decorativeElements.corners !== false // Default to true if not specified const showBorders = decorativeElements.borders !== false // Default to true if not specified return ( <div className="relative h-screen w-full overflow-hidden bg-black"> {/* Decorative background pattern */} <div className="absolute inset-0 bg-[url('/decorative/floral-pattern.png')] bg-repeat opacity-5"></div> {/* Image Grid */} <div className={`grid ${layoutClass} h-full w-full`}> {displayImages.map((image, index) => { const imageUrl = image.startsWith("http") ? image : getR2ImageUrl(config.id, image.split("/").pop() || "") return ( <div key={index} className="relative h-full w-full overflow-hidden"> <motion.div initial={{ scale: 1.1, opacity: 0 }} animate={{ scale: 1, opacity: 1 }} transition={{ duration: 1.5, delay: index * 0.2 }} className="absolute inset-0" > <img src={imageUrl || "/placeholder.svg"} alt={`Wedding portrait ${index + 1}`} className="h-full w-full object-cover object-center" /> <div className="absolute inset-0 bg-gradient-to-b from-black/40 via-transparent to-black/70" style={{ opacity: overlayOpacity + 0.2 }} /> </motion.div> </div> ) })} </div> {/* Decorative frame - only show if borders are enabled */} {showBorders && ( <motion.div className="absolute inset-4 border border-white/10 pointer-events-none z-10" initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ duration: 1, delay: 0.5 }} /> )} {/* Content overlay */} <div className="absolute inset-0 flex flex-col items-center justify-center z-20 px-4"> <div className="max-w-4xl text-center"> {/* Decorative element */} <motion.div className="mb-6 flex justify-center" initial={{ opacity: 0, y: -20 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 1, delay: 0.6 }} > <Heart className="h-8 w-8 text-rose-300/80" /> </motion.div> <motion.h1 className={`${textColor} text-3xl sm:text-5xl md:text-6xl lg:text-7xl font-light mb-6 tracking-wide`} initial={{ opacity: 0, y: 20 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 1, delay: 0.8 }} > {config.title} </motion.h1> {/* Elegant divider */} <motion.div className="my-6 flex items-center justify-center gap-4" initial={{ opacity: 0, scaleX: 0 }} animate={{ opacity: 1, scaleX: 1 }} transition={{ duration: 1.2, delay: 1 }} > <div className="h-px w-16 bg-white/60"></div> <div className="w-2 h-2 rounded-full bg-rose-300/80"></div> <div className="h-px w-16 bg-white/60"></div> </motion.div> {heroConfig.subtitle && ( <motion.p className={`${textColor} max-w-xl mx-auto text-lg sm:text-xl tracking-wide`} initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ duration: 1, delay: 1.2 }} > {heroConfig.subtitle} </motion.p> )} <motion.div className={`${textColor} mt-8 text-lg sm:text-xl tracking-widest`} initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ duration: 1, delay: 1.4 }} > {config.date} </motion.div> </div> </div> {/* Photographer credit */} <motion.div className="absolute bottom-8 left-0 right-0 text-center z-20" initial={{ opacity: 0 }} animate={{ opacity: 1 }} transition={{ duration: 1, delay: 1.6 }} > <p className="text-white/70 text-xs tracking-widest">{config.photographerCredit}</p> </motion.div> {/* Scroll Indicator */} {(heroConfig.scrollIndicator ?? true) && ( <motion.div className="absolute bottom-20 left-0 right-0 flex justify-center z-20" initial={{ opacity: 0, y: -10 }} animate={{ opacity: 1, y: 0, transition: { duration: 0.8, delay: 1.8, repeat: Number.POSITIVE_INFINITY, repeatType: "reverse", repeatDelay: 0.5, }, }} > <div className="p-2 border border-white/20 rounded-full"> <ChevronDown className="h-5 w-5 text-white/70" /> </div> </motion.div> )} {/* Corner decorations - only show if corners are enabled */} {showCorners && ( <div className="absolute inset-0 pointer-events-none z-10"> <motion.img src="/decorative/floral-corner-1.png" alt="Decorative corner" className="absolute top-8 left-8 w-16 h-16 opacity-40" initial={{ opacity: 0, scale: 0.8 }} animate={{ opacity: 0.4, scale: 1 }} transition={{ duration: 1, delay: 1.2 }} /> <motion.img src="/decorative/floral-corner-1.png" alt="Decorative corner" className="absolute top-8 right-8 w-16 h-16 opacity-40 transform -scale-x-100" initial={{ opacity: 0, scale: 0.8 }} animate={{ opacity: 0.4, scale: 1 }} transition={{ duration: 1, delay: 1.4 }} /> <motion.img src="/decorative/floral-corner-1.png" alt="Decorative corner" className="absolute bottom-8 left-8 w-16 h-16 opacity-40 transform -scale-y-100" initial={{ opacity: 0, scale: 0.8 }} animate={{ opacity: 0.4, scale: 1 }} transition={{ duration: 1, delay: 1.6 }} /> <motion.img src="/decorative/floral-corner-1.png" alt="Decorative corner" className="absolute bottom-8 right-8 w-16 h-16 opacity-40 transform -scale-x-100 -scale-y-100" initial={{ opacity: 0, scale: 0.8 }} animate={{ opacity: 0.4, scale: 1 }} transition={{ duration: 1, delay: 1.8 }} /> </div> )} </div> ) }
Editor is loading...
Leave a Comment