troylusty.com/src/components/Slideshow.astro
Troy db23c4aee4
All checks were successful
Docker / build-and-push-image (push) Successful in 1m58s
fix: always show project title over hero image on mobile
2025-07-25 19:15:46 +01:00

78 lines
2.3 KiB
Text

---
import { Image } from "astro:assets";
import type { CollectionEntry } from "astro:content";
interface Props {
images: CollectionEntry<"projects">[];
interval?: number;
}
const { interval = 3000, images } = Astro.props;
---
<div
class="group relative min-h-[50svh] w-full overflow-hidden"
data-interval={interval}
>
{
images.map((image: any, index: number) => (
<div
class="absolute top-0 left-0 h-full w-full transition-opacity duration-500"
style={`opacity: ${index === 0 ? 1 : 0}; z-index: ${
index === 0 ? 10 : 1
}`}
data-slide-index={index}
>
<a href={`/${image.collection}/${image.slug}`}>
<Image
src={image.data.image.url}
alt={`Slide ${index + 1}`}
class="h-full w-full rounded-sm object-cover transition-all duration-300 group-hover:brightness-50"
loading="eager"
{...(index === 0 && { priority: true })}
/>
<div class="relative opacity-100 transition-all delay-100 duration-300 ease-in-out group-hover:opacity-100 md:opacity-0">
<p class="bg-primary/50 absolute right-5 bottom-5 rounded-sm px-1 py-0.5 font-medium text-white md:bg-transparent">
{image.data.title}
</p>
</div>
</a>
</div>
))
}
</div>
<script>
const images = Array.from(
document.querySelectorAll<HTMLElement>("[data-slide-index]"),
);
let currentImageIndex = 0;
const closestRelativeElement = document
.querySelector<HTMLElement>("[data-slide-index]")
?.closest(".relative") as HTMLElement | null;
const interval = Number(closestRelativeElement?.dataset?.interval) || 3000;
for (let i = images.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[images[i], images[j]] = [images[j], images[i]];
}
images.forEach((img, index) => {
img.style.opacity = index === 0 ? "1" : "0";
img.style.zIndex = index === 0 ? "10" : "1";
});
function showNextImage() {
images[currentImageIndex].style.opacity = "0";
images[currentImageIndex].style.zIndex = "1";
currentImageIndex = (currentImageIndex + 1) % images.length;
images[currentImageIndex].style.opacity = "1";
images[currentImageIndex].style.zIndex = "10";
}
setInterval(showNextImage, interval);
</script>