Files
my-website-v2/frontend/islands/ImageCarousel.tsx

83 lines
2.7 KiB
TypeScript

import { useState } from "preact/hooks";
export const ImageCarousel = function ImageCarousel(props: ImageCarouselProps) {
const [currentImageIndex, setCurrentImageIndex] = useState(0);
const nextImage = (e: Event) => {
e.stopPropagation();
if (props.images && props.images?.length > 0) {
const localImage = props.images;
setCurrentImageIndex((prev) => (prev + 1) % localImage.length || 0);
}
};
const prevImage = (e: Event) => {
e.stopPropagation();
if (props.images && props.images.length > 0) {
const localImage = props.images;
setCurrentImageIndex(
(prev) => (prev - 1 + localImage.length) % localImage.length,
);
}
};
return (
<div class="relative rounded overflow-hidden bg-gray-100 dark:bg-gray-800">
<div class="relative w-full h-96">
{props.images.map((image, index) => (
<img
key={index}
src={image}
alt={`screenshot ${index + 1}`}
class={`absolute inset-0 w-full h-full object-contain transition-opacity duration-500 ${
index === currentImageIndex ? "opacity-100" : "opacity-0"
}`}
/>
))}
</div>
{props.images.length > 1 && (
<>
<button
type="button"
onClick={prevImage}
class="absolute left-2 top-1/2 -translate-y-1/2 bg-black/50 hover:bg-black/70 text-white rounded-full w-10 h-10 flex items-center justify-center transition-all"
aria-label="Previous image"
>
</button>
<button
type="button"
onClick={nextImage}
class="absolute right-2 top-1/2 -translate-y-1/2 bg-black/50 hover:bg-black/70 text-white rounded-full w-10 h-10 flex items-center justify-center transition-all"
aria-label="Next image"
>
</button>
<div class="absolute bottom-4 left-1/2 -translate-x-1/2 flex gap-2 bg-black/30 px-3 py-2 rounded-full">
{props.images.map((_, index) => (
<button
key={index}
type="button"
onClick={(e) => {
e.stopPropagation();
setCurrentImageIndex(index);
}}
class={`w-2.5 h-2.5 rounded-full transition-all ${
index === currentImageIndex
? "bg-white scale-125"
: "bg-white/50 hover:bg-white/75"
}`}
aria-label={`Go to image ${index + 1}`}
/>
))}
</div>
</>
)}
</div>
);
};
type ImageCarouselProps = {
images: Array<string>;
};