Files
e-tib.com/components/blocks/HeroSection.tsx
Marc Mintel bf8073f5bf
All checks were successful
Build & Deploy / 🔍 Prepare (push) Successful in 1m10s
Build & Deploy / 🧪 QA (push) Successful in 1m17s
Build & Deploy / 🏗️ Build (push) Successful in 2m2s
Build & Deploy / 🚀 Deploy (push) Successful in 26s
Build & Deploy / 🧪 Post-Deploy Verification (push) Has been skipped
Build & Deploy / 🔔 Notify (push) Successful in 3s
perf: optimize LCP images and enable AVIF
2026-07-01 13:35:50 +02:00

101 lines
4.1 KiB
TypeScript

'use client';
import React from 'react';
import Image from 'next/image';
import { usePathname } from 'next/navigation';
import { Badge, Container, Heading } from '@/components/ui';
import { Button } from '@/components/ui/Button';
export interface HeroSectionProps {
title: string;
badge?: string;
subtitle?: string;
backgroundImage?: any;
alignment?: 'left' | 'center';
ctaLabel?: string;
ctaHref?: string;
}
// CSS animations replace Framer Motion for better LCP
export const HeroSection: React.FC<HeroSectionProps> = (props) => {
const { title, badge, subtitle, backgroundImage, alignment, ctaLabel, ctaHref } = props;
const bgSrc = backgroundImage?.sizes?.card?.url || backgroundImage?.url;
const pathname = usePathname();
return (
<section
className={`relative min-h-[35vh] md:min-h-[50vh] flex items-center pt-28 pb-10 md:pt-36 md:pb-24 overflow-hidden bg-neutral-dark ${alignment === 'center' ? 'justify-center text-center' : ''}`}
>
{bgSrc && (
<div
key={`hero-bg-${pathname}`}
className="absolute inset-0 z-0 animate-hero-zoom-out"
>
<Image
src={bgSrc}
alt={title || 'Hero Background'}
fill
className="object-cover filter contrast-110 saturate-110 brightness-95"
style={{
objectPosition: `${backgroundImage?.focalX ?? 50}% ${backgroundImage?.focalY ?? 50}%`,
}}
sizes="100vw"
quality={50}
priority
/>
{/* Cinematic Color Grading Overlay */}
<div className="absolute inset-0 bg-[#0a192f]/30 z-[2] mix-blend-multiply" />
{/* Dramatic Vignette & Fade to content */}
<div className="absolute inset-0 bg-[radial-gradient(ellipse_at_center,_var(--tw-gradient-stops))] from-transparent via-black/20 to-black/80 z-[2]" />
<div className="absolute inset-0 bg-gradient-to-t from-neutral-dark via-neutral-dark/60 to-transparent z-[3]" />
{/* Top Fade for Header Navigation Readability */}
<div className="absolute top-0 left-0 w-full h-48 bg-gradient-to-b from-black/70 to-transparent z-[3] pointer-events-none" />
</div>
)}
<Container className={`relative z-10 ${alignment === 'center' ? 'max-w-5xl' : ''}`}>
<div
key={`hero-content-${pathname}`}
className={`max-w-4xl ${alignment === 'center' ? 'mx-auto' : ''}`}
>
{badge && (
<div className="animate-hero-fade-in-up" style={{ animationDelay: '0.1s', opacity: 0, animationFillMode: 'forwards' }}>
<Badge variant="saturated" className="mb-4 md:mb-8 shadow-lg">
{badge}
</Badge>
</div>
)}
<div className="animate-hero-fade-in-up" style={{ animationDelay: badge ? '0.25s' : '0.1s', opacity: 0, animationFillMode: 'forwards' }}>
<Heading level={1} size="section" variant="white" align={alignment || 'left'} className="mb-4 md:mb-8">
{title}
</Heading>
</div>
{subtitle && (
<div className="animate-hero-fade-in-up" style={{ animationDelay: badge ? '0.4s' : '0.25s', opacity: 0, animationFillMode: 'forwards' }}>
<p className={`text-lg md:text-2xl text-white/70 font-medium leading-relaxed max-w-2xl ${alignment === 'center' ? 'mx-auto' : ''}`}>
{subtitle}
</p>
</div>
)}
{ctaLabel && ctaHref && (
<div className={`mt-8 animate-hero-fade-in-up ${alignment === 'center' ? 'flex flex-wrap justify-center gap-4' : 'flex flex-wrap gap-4'}`} style={{ animationDelay: badge ? '0.55s' : '0.4s', opacity: 0, animationFillMode: 'forwards' }}>
<Button
href={ctaHref}
variant="accent"
size="lg"
>
{ctaLabel}
<span className="ml-3 transition-transform group-hover/btn:translate-x-2">
&rarr;
</span>
</Button>
</div>
)}
</div>
</Container>
</section>
);
};