Files
egfh-website/src/components/BannerRotator.astro
T
2026-06-22 06:40:49 -04:00

92 lines
2.4 KiB
Plaintext

---
import type { HomepageBannerImage } from '../lib/fallback-data';
type Props = {
images: HomepageBannerImage[];
randomizeAfterFirst?: boolean;
};
const { images, randomizeAfterFirst = false } = Astro.props;
const slides = images.length > 0 ? images : [{ src: '/images/banner.png', alt: 'Swansea Airport banner' }];
---
<div class="banner-rotator" data-banner-rotator data-randomize-after-first={randomizeAfterFirst ? 'true' : undefined}>
{slides.map((image, index) => (
<img
class:list={['banner-slide', { active: index === 0 }]}
src={image.src}
alt={image.alt}
loading={index === 0 ? 'eager' : 'lazy'}
decoding="async"
data-banner-slide
/>
))}
</div>
{slides.length > 1 && (
<script>
(() => {
const root = document.querySelector('[data-banner-rotator]');
if (!root || window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
const slides = Array.from(root.querySelectorAll('[data-banner-slide]'));
if (slides.length < 2) return;
if (root.getAttribute('data-randomize-after-first') === 'true') {
const firstSlide = slides[0];
const restSlides = slides.slice(1);
for (let index = restSlides.length - 1; index > 0; index -= 1) {
const swapIndex = Math.floor(Math.random() * (index + 1));
[restSlides[index], restSlides[swapIndex]] = [restSlides[swapIndex], restSlides[index]];
}
slides.splice(0, slides.length, firstSlide, ...restSlides);
}
let currentIndex = 0;
window.setInterval(() => {
slides[currentIndex].classList.remove('active');
currentIndex = (currentIndex + 1) % slides.length;
slides[currentIndex].classList.add('active');
}, 3500);
})();
</script>
)}
<style>
.banner-rotator {
position: relative;
width: 100%;
min-height: clamp(9rem, 21vw, 16rem);
overflow: hidden;
isolation: isolate;
background: #dcecff;
}
.banner-slide {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
display: block;
object-fit: cover;
opacity: 0;
transform: scale(1.035);
transition:
opacity 1.1s ease,
transform 7s ease;
}
.banner-slide.active {
opacity: 1;
transform: scale(1);
}
@media (prefers-reduced-motion: reduce) {
.banner-slide {
transition: none;
}
}
</style>