fix(ui): remove hero video image wrapper and fix carousel edge sticking padding
All checks were successful
Build & Deploy / 🔍 Prepare (push) Successful in 1m24s
Build & Deploy / 🧪 QA (push) Successful in 1m45s
Build & Deploy / 🏗️ Build (push) Successful in 3m11s
Build & Deploy / 🚀 Deploy (push) Successful in 38s
Build & Deploy / 🧪 Post-Deploy Verification (push) Successful in 1m8s
Build & Deploy / 🔔 Notify (push) Successful in 2s
All checks were successful
Build & Deploy / 🔍 Prepare (push) Successful in 1m24s
Build & Deploy / 🧪 QA (push) Successful in 1m45s
Build & Deploy / 🏗️ Build (push) Successful in 3m11s
Build & Deploy / 🚀 Deploy (push) Successful in 38s
Build & Deploy / 🧪 Post-Deploy Verification (push) Successful in 1m8s
Build & Deploy / 🔔 Notify (push) Successful in 2s
This commit is contained in:
@@ -4,6 +4,7 @@ import { Button } from '@/components/ui/Button';
|
|||||||
import Image from 'next/image';
|
import Image from 'next/image';
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { usePathname } from 'next/navigation';
|
import { usePathname } from 'next/navigation';
|
||||||
|
import { preload } from 'react-dom';
|
||||||
|
|
||||||
interface HeroVideoProps {
|
interface HeroVideoProps {
|
||||||
data?: any;
|
data?: any;
|
||||||
@@ -41,6 +42,10 @@ export function HeroVideo(props: HeroVideoProps) {
|
|||||||
const secondaryCtaLabel = props.secondaryCtaLabel || data?.secondaryCtaLabel || (currentLocale === 'de' ? 'Projekt anfragen' : 'Inquire Project');
|
const secondaryCtaLabel = props.secondaryCtaLabel || data?.secondaryCtaLabel || (currentLocale === 'de' ? 'Projekt anfragen' : 'Inquire Project');
|
||||||
const secondaryCtaHref = props.secondaryCtaHref || data?.secondaryCtaHref || `/${currentLocale}/contact`;
|
const secondaryCtaHref = props.secondaryCtaHref || data?.secondaryCtaHref || `/${currentLocale}/contact`;
|
||||||
|
|
||||||
|
if (posterSrc) {
|
||||||
|
preload(posterSrc, { as: 'image' });
|
||||||
|
}
|
||||||
|
|
||||||
const [videoSrcLoaded, setVideoSrcLoaded] = useState(false);
|
const [videoSrcLoaded, setVideoSrcLoaded] = useState(false);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let interactionTriggered = false;
|
let interactionTriggered = false;
|
||||||
@@ -73,28 +78,30 @@ export function HeroVideo(props: HeroVideoProps) {
|
|||||||
{/* Background color while video loads */}
|
{/* Background color while video loads */}
|
||||||
<div className="absolute inset-0 z-0 bg-neutral-dark" />
|
<div className="absolute inset-0 z-0 bg-neutral-dark" />
|
||||||
|
|
||||||
{/* ALWAYS render the Next.js optimized Image as the LCP element */}
|
{/* Dramatic Vignette & Fade to content */}
|
||||||
<Image
|
<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]" />
|
||||||
key={`img-${pathname}-${posterSrc}`}
|
<div className="absolute inset-0 bg-gradient-to-t from-neutral-dark via-neutral-dark/60 to-transparent z-[3]" />
|
||||||
src={posterSrc}
|
|
||||||
alt={posterAlt}
|
|
||||||
fill
|
|
||||||
className="object-cover z-[1] pointer-events-none filter contrast-125 saturate-110 brightness-90"
|
|
||||||
sizes="100vw"
|
|
||||||
priority
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Render video on top if available, but defer src to avoid blocking LCP */}
|
{/* Top Fade for Header Navigation Readability */}
|
||||||
{videoUrl && (
|
<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" />
|
||||||
|
|
||||||
|
{videoUrl ? (
|
||||||
<video
|
<video
|
||||||
key={`${pathname}-${videoUrl}`}
|
key={`${pathname}-${videoUrl}`}
|
||||||
className="absolute inset-0 w-full h-full object-cover z-[2] pointer-events-none filter contrast-125 saturate-110 brightness-90"
|
className="absolute inset-0 w-full h-full object-cover z-[1] pointer-events-none filter contrast-125 saturate-110 brightness-90"
|
||||||
src={videoSrcLoaded ? videoUrl : undefined}
|
src={videoUrl}
|
||||||
|
poster={posterSrc}
|
||||||
autoPlay
|
autoPlay
|
||||||
muted
|
muted
|
||||||
loop
|
loop
|
||||||
playsInline
|
playsInline
|
||||||
preload="none"
|
preload="auto"
|
||||||
|
/>
|
||||||
|
) : (
|
||||||
|
<div
|
||||||
|
key={`img-${pathname}-${posterSrc}`}
|
||||||
|
className="absolute inset-0 w-full h-full object-cover z-[1] pointer-events-none filter contrast-125 saturate-110 brightness-90"
|
||||||
|
style={{ backgroundImage: `url(${posterSrc})`, backgroundSize: 'cover', backgroundPosition: 'center' }}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -115,7 +115,7 @@ export function ReferencesSlider(props: ReferencesSliderProps) {
|
|||||||
onMouseLeave={onMouseLeave}
|
onMouseLeave={onMouseLeave}
|
||||||
onMouseUp={onMouseUp}
|
onMouseUp={onMouseUp}
|
||||||
onMouseMove={onMouseMove}
|
onMouseMove={onMouseMove}
|
||||||
className={`select-none flex gap-6 overflow-x-auto pb-8 pt-4 px-6 md:px-[max(2rem,calc((100vw-1280px)/2))] lg:px-[max(2.5rem,calc((100vw-1280px)/2))] [scrollbar-width:none] [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden ${isDragging ? 'cursor-grabbing snap-none' : 'cursor-grab snap-x snap-mandatory'}`}
|
className={`select-none flex gap-6 overflow-x-auto pb-8 pt-4 px-4 sm:px-6 md:px-8 lg:px-10 xl:px-[calc(50vw_-_640px_+_3rem)] 2xl:px-[calc(50vw_-_700px_+_4rem)] [scrollbar-width:none] [-ms-overflow-style:none] [&::-webkit-scrollbar]:hidden ${isDragging ? 'cursor-grabbing snap-none' : 'cursor-grab snap-x snap-mandatory'}`}
|
||||||
>
|
>
|
||||||
{references.map((ref, i) => {
|
{references.map((ref, i) => {
|
||||||
const imgSrc = ref.image
|
const imgSrc = ref.image
|
||||||
|
|||||||
Reference in New Issue
Block a user