feat: add homepage image carousel with controls

This commit is contained in:
headpatsyou 2026-01-07 13:05:40 +00:00
parent ac022933c8
commit c4541f461a
4 changed files with 136 additions and 0 deletions

View file

@ -1,7 +1,10 @@
import { ImageCarousel } from "@/components/layout/ImageCarousel";
export default function EnHome() {
return (
<section className="hero" aria-labelledby="home-title">
<div className="container">
<ImageCarousel />
<h1 id="home-title" className="title">Portuguese Powerlifting Association</h1>
<p className="subtitle">Accessible. Transparent. For all athletes.</p>
<div className="mt-4 flex gap-2">

View file

@ -152,6 +152,72 @@ p { font-size: 1rem; line-height: 1.6; color: var(--foreground); }
margin-top: 0.5rem;
color: var(--color-muted);
}
/* Carousel */
.carousel {
position: relative;
overflow: hidden;
border-radius: 12px;
border: 1px solid var(--color-border);
margin-bottom: 1.5rem;
}
.carousel-viewport {
position: relative;
width: 100%;
height: 320px;
background: #f8f8f8;
}
.carousel-slide {
position: absolute;
inset: 0;
opacity: 0;
transition: opacity 250ms ease;
}
.carousel-slide.active {
opacity: 1;
}
.carousel-controls {
position: absolute;
inset: auto 0 0 0;
display: flex;
align-items: center;
justify-content: center;
gap: 0.75rem;
padding: 0.5rem 0.75rem;
background: linear-gradient(180deg, rgba(0,0,0,0) 0%, rgba(0,0,0,0.35) 100%);
}
.carousel-btn {
background: rgba(255,255,255,0.9);
border: 1px solid var(--color-border);
border-radius: 999px;
width: 36px;
height: 36px;
display: inline-flex;
align-items: center;
justify-content: center;
font-size: 1.25rem;
cursor: pointer;
}
.carousel-btn:hover,
.carousel-btn:focus-visible {
background: #fff;
border-color: var(--color-green);
}
.carousel-dots {
display: inline-flex;
gap: 0.4rem;
}
.carousel-dot {
width: 12px;
height: 12px;
border-radius: 50%;
border: 1px solid #fff;
background: rgba(255,255,255,0.6);
cursor: pointer;
}
.carousel-dot.active {
background: #fff;
}
.btn {
display: inline-flex;
align-items: center;

View file

@ -1,7 +1,10 @@
import { ImageCarousel } from "@/components/layout/ImageCarousel";
export default function PtHome() {
return (
<section className="hero" aria-labelledby="home-title">
<div className="container">
<ImageCarousel />
<h1 id="home-title" className="title">Associação Portuguesa de Powerlifting</h1>
<p className="subtitle">Acessível. Transparente. Para todos os atletas.</p>
<div className="mt-4 flex gap-2">

View file

@ -0,0 +1,64 @@
"use client";
import Image from "next/image";
import { useEffect, useState } from "react";
const slides = [
{ src: "/content/images/1.png", alt: "Powerlifting highlight 1" },
{ src: "/content/images/2.png", alt: "Powerlifting highlight 2" },
{ src: "/content/images/3.png", alt: "Powerlifting highlight 3" },
];
export function ImageCarousel() {
const [index, setIndex] = useState(0);
useEffect(() => {
const id = setInterval(() => {
setIndex((prev) => (prev + 1) % slides.length);
}, 5000);
return () => clearInterval(id);
}, []);
const goTo = (i: number) => setIndex(i % slides.length);
const prev = () => setIndex((prev) => (prev - 1 + slides.length) % slides.length);
const next = () => setIndex((prev) => (prev + 1) % slides.length);
return (
<section aria-label="Destaques" className="carousel" role="region">
<div className="carousel-viewport" aria-live="polite">
{slides.map((slide, i) => (
<div
key={slide.src}
className={`carousel-slide ${i === index ? "active" : ""}`}
aria-hidden={i !== index ? "true" : "false"}
>
<Image
src={slide.src}
alt={slide.alt}
fill
className="object-cover"
sizes="(max-width: 768px) 100vw, 1200px"
priority={i === 0}
/>
</div>
))}
</div>
<div className="carousel-controls">
<button type="button" onClick={prev} aria-label="Imagem anterior" className="carousel-btn"></button>
<div className="carousel-dots" role="tablist" aria-label="Selecionar imagem do carrossel">
{slides.map((_, i) => (
<button
key={i}
type="button"
role="tab"
aria-selected={i === index ? "true" : "false"}
aria-label={`Ir para imagem ${i + 1}`}
className={`carousel-dot ${i === index ? "active" : ""}`}
onClick={() => goTo(i)}
/>
))}
</div>
<button type="button" onClick={next} aria-label="Próxima imagem" className="carousel-btn"></button>
</div>
</section>
);
}