Only hero images for CTA carousels, honour reduced motion

This commit is contained in:
encie22 committed 2026-10-16 09:17:58 +10:30
1 parent 70af555189
commit af8f99feb0
2 files changed
+48 -37

No files matched your search

+36 -27
View File
@@ -20,6 +20,7 @@ interface Props {
quality?: number;
height?: number;
shuffle?: boolean;
eagerCount?: number;
}
const {
@@ -37,7 +38,8 @@ const {
foregroundOpacity = "opacity-50",
quality = "80",
height,
shuffle = false
shuffle = false,
eagerCount = 2
} = Astro.props as Props;
const imagesArray = shuffle ? shuffleArray(images) : images;
@@ -64,7 +66,7 @@ const imagesArray = shuffle ? shuffleArray(images) : images;
alt={
typeof altText === "function" ? altText(index) : (altText ?? "")
}
loading={index < 2 ? "eager" : "lazy"}
loading={index < eagerCount ? "eager" : "lazy"}
aria-hidden={index === 0 ? "false" : "true"}
layout="full-width"
fit="cover"
@@ -91,34 +93,41 @@ const imagesArray = shuffle ? shuffleArray(images) : images;
>
let currentIndex = 0;
setInterval(() => {
const current = document.querySelectorAll(
`[data-id="${carouselId}-${currentIndex}"]`
)[0];
const nextIndex = (currentIndex + 1) % imageCount;
const next = document.querySelectorAll(
`[data-id="${carouselId}-${nextIndex}"]`
)[0];
// Honour reduced-motion: leave the first image showing, no rotation.
const reduceMotion = window.matchMedia(
"(prefers-reduced-motion: reduce)"
).matches;
if (!current || !next) return;
if (!reduceMotion) {
setInterval(() => {
const current = document.querySelectorAll(
`[data-id="${carouselId}-${currentIndex}"]`
)[0];
const nextIndex = (currentIndex + 1) % imageCount;
const next = document.querySelectorAll(
`[data-id="${carouselId}-${nextIndex}"]`
)[0];
// Fade out current, fade in next
current.classList.add("opacity-0");
current.setAttribute("aria-hidden", "true");
if (!current || !next) return;
next.classList.remove("opacity-0", "hidden");
next.setAttribute("aria-hidden", "false");
// Fade out current, fade in next
current.classList.add("opacity-0");
current.setAttribute("aria-hidden", "true");
const preloadIndex = (nextIndex + 1) % imageCount;
const preloadImage = document.querySelectorAll(
`[data-id="${carouselId}-${preloadIndex}"]`
)[0];
if (preloadImage) {
preloadImage.classList.add("opacity-0");
preloadImage.classList.remove("hidden");
preloadImage.setAttribute("aria-hidden", "true");
}
next.classList.remove("opacity-0", "hidden");
next.setAttribute("aria-hidden", "false");
currentIndex = nextIndex;
}, interval);
const preloadIndex = (nextIndex + 1) % imageCount;
const preloadImage = document.querySelectorAll(
`[data-id="${carouselId}-${preloadIndex}"]`
)[0];
if (preloadImage) {
preloadImage.classList.add("opacity-0");
preloadImage.classList.remove("hidden");
preloadImage.setAttribute("aria-hidden", "true");
}
currentIndex = nextIndex;
}, interval);
}
</script>
+12 -10
View File
@@ -17,28 +17,28 @@ import { Image } from "astro:assets";
import { Icon } from "astro-icon/components";
import { convertEagerImagesImportGlobToArray } from "@lib/utils";
import {
convertEagerImagesImportGlobToArray,
getProjectHero
} from "@lib/utils";
const heroImages = import.meta.glob<{ default: ImageMetadata; eager: true }>(
"../assets/img/hero/*"
);
const heroImagesArray = await convertEagerImagesImportGlobToArray(heroImages);
const imagesForCTA = import.meta.glob<{ default: ImageMetadata; eager: true }>([
"../assets/img/hero/*",
"../assets/img/project-heros/*",
"../assets/img/projects/**"
]);
const imagesForCTAArray =
await convertEagerImagesImportGlobToArray(imagesForCTA);
const projects = (
await getCollection("projects", ({ data }) => data.frontPage)
).sort(
(a, b) => (a.data.frontPage?.order || 0) - (b.data.frontPage?.order || 1)
);
// Curated carousel set: site heroes + heroes of featured projects only, instead of every image in the repo. Shared by both CTA carousels.
const imagesForCTAArray = [
...heroImagesArray,
...projects.map((project) => getProjectHero(project))
];
const awards = (await getCollection("awards")).sort(
(a, b) => b.data.date.valueOf() - a.data.date.valueOf()
);
@@ -120,6 +120,7 @@ const tracks = (
quality={5}
height={192}
shuffle={true}
eagerCount={0}
><div class="flex h-full w-full items-center">
<a
href="/contact/"
@@ -207,6 +208,7 @@ const tracks = (
quality={5}
height={384}
shuffle={true}
eagerCount={0}
/>
</div>
</section>