Only hero images for CTA carousels, honour reduced motion
This commit is contained in:
2 files changed
+48
-37
No files matched your search
@@ -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
@@ -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>
|
||||
|
||||
Reference in new issue
Block a user