diff --git a/src/components/Gallery.jsx b/src/components/Gallery.jsx index b51a99ce..263e0d0e 100644 --- a/src/components/Gallery.jsx +++ b/src/components/Gallery.jsx @@ -1,4 +1,4 @@ -import { useState } from "react"; +import { useEffect, useState } from "react"; import { GiPlainSquare, GiSquare } from "react-icons/gi"; import { ImCross } from "react-icons/im"; import { formatDate } from "../lib/format"; @@ -35,6 +35,27 @@ export default function Gallery({ images, currentPage, lastPage, total, perPage else window.location.href = `${pageUrl(currentPage - 1)}?index=${perPage - 1}`; }; + // Re-bound every render so the handlers always see the current image. + // Lightbox open: step through images. Overview: step through gallery pages (wrapping). + useEffect(() => { + const onKey = (e) => { + if (e.ctrlKey || e.metaKey || e.altKey) return; + const forward = e.key === "ArrowRight" || e.key === "l"; + const back = e.key === "ArrowLeft" || e.key === "h"; + if (active !== null) { + if (forward) next(); + else if (back) prev(); + else if (e.key === "Escape") show(null); + } else if (forward) { + window.location.href = pageUrl(currentPage === lastPage ? 1 : currentPage + 1); + } else if (back) { + window.location.href = pageUrl(currentPage === 1 ? lastPage : currentPage - 1); + } + }; + window.addEventListener("keydown", onKey); + return () => window.removeEventListener("keydown", onKey); + }); + const current = active === null ? null : images[active]; return ( diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro index 09453d3d..d80c5939 100644 --- a/src/layouts/Layout.astro +++ b/src/layouts/Layout.astro @@ -11,12 +11,16 @@ interface Props { /** Document title prefix; "