mirror of
https://github.com/Lapikud/tipilan.git
synced 2026-09-22 15:22:59 +00:00
Carusel changes to previous ver, sponsors L to R
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect, useCallback } from "react";
|
||||
import { useState, useEffect, useCallback, useRef } from "react";
|
||||
import Image from "next/image";
|
||||
import { Link } from "@/i18n/routing";
|
||||
import { vipnagorgialla } from "@/components/Vipnagorgialla";
|
||||
@@ -64,6 +64,7 @@ const slides: Slide[] = [
|
||||
export default function TeaserCarousel() {
|
||||
const t = useTranslations("home.teaser");
|
||||
const [current, setCurrent] = useState(0);
|
||||
const intervalRef = useRef<ReturnType<typeof setInterval> | null>(null);
|
||||
|
||||
const next = useCallback(
|
||||
() => setCurrent((c) => (c + 1) % slides.length),
|
||||
@@ -71,66 +72,91 @@ export default function TeaserCarousel() {
|
||||
);
|
||||
const prev = () => setCurrent((c) => (c - 1 + slides.length) % slides.length);
|
||||
|
||||
useEffect(() => {
|
||||
const id = setInterval(next, 5000);
|
||||
return () => clearInterval(id);
|
||||
const restartAutoplay = useCallback(() => {
|
||||
if (intervalRef.current) {
|
||||
clearInterval(intervalRef.current);
|
||||
}
|
||||
intervalRef.current = setInterval(next, 5000);
|
||||
}, [next]);
|
||||
|
||||
useEffect(() => {
|
||||
restartAutoplay();
|
||||
|
||||
return () => {
|
||||
if (intervalRef.current) {
|
||||
clearInterval(intervalRef.current);
|
||||
}
|
||||
};
|
||||
}, [restartAutoplay]);
|
||||
|
||||
const headingOnRight = Boolean(slides[current]?.flip);
|
||||
|
||||
return (
|
||||
<div className="border-b-3 border-[#1F5673]">
|
||||
{/* Sliding track */}
|
||||
{/* Slides (fade transition + hero lift effect) */}
|
||||
<div className="relative h-[729px] overflow-hidden">
|
||||
<div
|
||||
className="flex h-full transition-transform duration-500 ease-in-out"
|
||||
style={{ transform: `translateX(-${current * 100}%)` }}
|
||||
>
|
||||
{slides.map((slide) => {
|
||||
const title = t(`${slide.key}.title`);
|
||||
const description = t(`${slide.key}.description`);
|
||||
return (
|
||||
<div key={slide.key} className="relative flex-none w-full h-full">
|
||||
{/* Background image */}
|
||||
<Image
|
||||
src={slide.image}
|
||||
alt={slide.imageAlt}
|
||||
fill
|
||||
className="object-cover object-center"
|
||||
/>
|
||||
{/* Overlay */}
|
||||
<div
|
||||
className={`absolute inset-0 ${slide.fullBrightness ? "" : "bg-gradient-to-r from-[#0E0F19]/90 via-[#0E0F19]/60 to-[#0E0F19]/20"}`}
|
||||
/>
|
||||
{slides.map((slide, i) => {
|
||||
const title = t(`${slide.key}.title`);
|
||||
const description = t(`${slide.key}.description`);
|
||||
const isActive = i === current;
|
||||
|
||||
{/* Content */}
|
||||
return (
|
||||
<div
|
||||
key={slide.key}
|
||||
className={`absolute inset-0 transition-opacity duration-700 ease-out ${
|
||||
isActive ? "opacity-100" : "opacity-0 pointer-events-none"
|
||||
}`}
|
||||
>
|
||||
{/* Background image */}
|
||||
<Image
|
||||
src={slide.image}
|
||||
alt={slide.imageAlt}
|
||||
fill
|
||||
className="object-cover object-center"
|
||||
/>
|
||||
|
||||
{/* Overlay */}
|
||||
<div
|
||||
className={`absolute inset-0 ${slide.fullBrightness ? "" : "bg-gradient-to-r from-[#0E0F19]/90 via-[#0E0F19]/60 to-[#0E0F19]/20"}`}
|
||||
/>
|
||||
|
||||
{/* Content */}
|
||||
<div
|
||||
className={`relative grid grid-cols-1 md:grid-cols-2 h-full ${slide.flip ? "md:[direction:rtl]" : ""}`}
|
||||
>
|
||||
<div
|
||||
className={`relative grid grid-cols-1 md:grid-cols-2 h-full ${slide.flip ? "md:[direction:rtl]" : ""}`}
|
||||
className={`flex flex-col justify-end px-8 py-8 md:px-12 md:py-10 ${slide.flip ? "md:[direction:ltr]" : ""}`}
|
||||
>
|
||||
{/* Title + description at bottom */}
|
||||
<div
|
||||
className={`flex flex-col gap-3 pb-16 ${slide.flip ? "md:items-end md:text-right md:ml-auto" : ""}`}
|
||||
>
|
||||
<Link href={slide.href}>
|
||||
<h3
|
||||
className={`${vipnagorgialla.className} font-bold italic text-[clamp(2.5rem,2rem+2.5vw,5rem)] leading-none text-[#EEE5E5] hover:text-[#00A3E0] transition`}
|
||||
>
|
||||
{title}
|
||||
</h3>
|
||||
</Link>
|
||||
<p
|
||||
className={`text-[1.1rem] leading-relaxed md:text-[clamp(0.875rem,0.75rem+0.5vw,1.1rem)] text-[#EEE5E5] max-w-prose ${slide.flip ? "md:text-right" : ""}`}
|
||||
>
|
||||
{description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Hero image */}
|
||||
<div
|
||||
className={`hidden md:block relative overflow-hidden ${slide.flip ? "md:[direction:ltr]" : ""}`}
|
||||
>
|
||||
<div
|
||||
className={`flex flex-col justify-between px-8 py-8 md:px-12 md:py-10 ${slide.flip ? "md:[direction:ltr]" : ""}`}
|
||||
>
|
||||
{/* Heading at top */}
|
||||
<h2
|
||||
className={`${vipnagorgialla.className} font-bold italic text-[clamp(2.5rem,1.5rem+4.5vw,4rem)] md:text-[64px] leading-none tracking-normal uppercase text-[#EEE5E5]`}
|
||||
>
|
||||
{highlightLAN(t("heading"))}
|
||||
</h2>
|
||||
{/* Title + description at bottom */}
|
||||
<div className="flex flex-col gap-3 pb-16">
|
||||
<Link href={slide.href}>
|
||||
<h3
|
||||
className={`${vipnagorgialla.className} font-bold italic text-[clamp(2.5rem,2rem+2.5vw,5rem)] leading-none text-[#EEE5E5] hover:text-[#00A3E0] transition`}
|
||||
>
|
||||
{title}
|
||||
</h3>
|
||||
</Link>
|
||||
<p className="text-[clamp(0.875rem,0.75rem+0.5vw,1.1rem)] text-[#EEE5E5] max-w-prose">
|
||||
{description}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{/* Hero image */}
|
||||
<div
|
||||
className={`hidden md:block relative ${slide.flip ? "md:[direction:ltr]" : ""}`}
|
||||
className="absolute inset-0 transition-transform duration-700 ease-out"
|
||||
style={{
|
||||
transform: isActive
|
||||
? "translateY(0)"
|
||||
: "translateY(110%)",
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
src={slide.hero}
|
||||
@@ -141,20 +167,52 @@ export default function TeaserCarousel() {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
{/* Floating heading (mobile) */}
|
||||
<div className="absolute top-5 inset-x-0 px-8 z-20 md:hidden pointer-events-none">
|
||||
<h2
|
||||
className={`${vipnagorgialla.className} font-bold italic text-[clamp(2rem,1.5rem+4.6vw,3rem)] leading-[0.95] tracking-normal uppercase text-[#EEE5E5] whitespace-normal break-words text-left max-w-[12ch]`}
|
||||
>
|
||||
{highlightLAN(t("heading"))}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
{/* Floating heading (desktop/tablet) */}
|
||||
<div className="absolute top-8 inset-x-0 px-4 sm:px-6 md:px-12 z-20 hidden md:flex pointer-events-none">
|
||||
<div
|
||||
className="transition-[flex-grow] duration-700 ease-out"
|
||||
style={{ flexGrow: headingOnRight ? 1 : 0 }}
|
||||
/>
|
||||
<h2
|
||||
className={`${vipnagorgialla.className} font-bold italic text-[64px] leading-none tracking-normal uppercase text-[#EEE5E5] whitespace-normal [overflow-wrap:anywhere] text-center shrink`}
|
||||
>
|
||||
{highlightLAN(t("heading"))}
|
||||
</h2>
|
||||
<div
|
||||
className="transition-[flex-grow] duration-700 ease-out"
|
||||
style={{ flexGrow: headingOnRight ? 0 : 1 }}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Arrow buttons */}
|
||||
<button
|
||||
onClick={prev}
|
||||
onClick={() => {
|
||||
prev();
|
||||
restartAutoplay();
|
||||
}}
|
||||
className="absolute left-4 top-1/2 -translate-y-1/2 w-10 h-10 flex items-center justify-center bg-[#0E0F19]/50 hover:bg-[#007CAB] text-[#EEE5E5] transition z-20"
|
||||
aria-label="Previous slide"
|
||||
>
|
||||
<span className="material-symbols-outlined">chevron_left</span>
|
||||
</button>
|
||||
<button
|
||||
onClick={next}
|
||||
onClick={() => {
|
||||
next();
|
||||
restartAutoplay();
|
||||
}}
|
||||
className="absolute right-4 top-1/2 -translate-y-1/2 w-10 h-10 flex items-center justify-center bg-[#0E0F19]/50 hover:bg-[#007CAB] text-[#EEE5E5] transition z-20"
|
||||
aria-label="Next slide"
|
||||
>
|
||||
@@ -166,7 +224,10 @@ export default function TeaserCarousel() {
|
||||
{slides.map((_, i) => (
|
||||
<button
|
||||
key={i}
|
||||
onClick={() => setCurrent(i)}
|
||||
onClick={() => {
|
||||
setCurrent(i);
|
||||
restartAutoplay();
|
||||
}}
|
||||
className={`w-3 h-3 rounded-full transition ${
|
||||
i === current
|
||||
? "bg-[#00A3E0]"
|
||||
|
||||
Reference in New Issue
Block a user