Skip to content

Commit 7725844

Browse files
committed
Add ZoomableImage component and use that in venue photo display
1 parent 9199d46 commit 7725844

2 files changed

Lines changed: 58 additions & 14 deletions

File tree

src/components/ZoomableImage.astro

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
---
2+
import type { ImageMetadata } from "astro";
3+
import { Image } from "astro:assets";
4+
5+
interface Props {
6+
src: ImageMetadata;
7+
alt: string;
8+
width?: number;
9+
zoomWidth?: number;
10+
class?: string;
11+
}
12+
13+
const { src, alt, width = 800, zoomWidth = 1600, class: cls } = Astro.props;
14+
const id = `zoom-${crypto.randomUUID()}`;
15+
---
16+
17+
<figure class:list={["relative", cls]}>
18+
{/* thumbnail img alt is the button's accessible name;
19+
aria-describedby adds the zoom affordance as a separate description
20+
(helps low-vision users who benefit from a larger image)
21+
without duplicating the name; the visually-identical figcaption below
22+
is hidden from assistive tech so it isn't announced a third time.
23+
Thanks for reading this long note :D */}
24+
<button popovertarget={id} aria-describedby={`${id}-hint`} class="block w-full cursor-zoom-in">
25+
<Image
26+
src={src}
27+
alt={alt}
28+
width={width}
29+
format="avif"
30+
class="w-full block rounded-lg object-cover aspect-4/3"
31+
/>
32+
</button>
33+
<span id={`${id}-hint`} class="sr-only">Zoom in</span>
34+
<figcaption aria-hidden="true" class="absolute inset-x-0 bottom-0 rounded-b-lg bg-linear-to-t from-black/70 to-transparent px-4 pt-10 pb-3 text-left font-mono text-xs md:text-sm text-white">
35+
{alt}
36+
</figcaption>
37+
38+
<div id={id} popover class="m-auto w-fit h-fit max-w-none p-0 border-0 bg-transparent backdrop:bg-black/80">
39+
<button
40+
popovertarget={id}
41+
popovertargetaction="hide"
42+
aria-label="Close"
43+
class="absolute top-3 right-3 w-9 h-9 rounded-full bg-black/70 text-white text-lg leading-none cursor-pointer"
44+
>
45+
46+
</button>
47+
<Image
48+
src={src}
49+
alt={alt}
50+
width={zoomWidth}
51+
format="avif"
52+
loading="lazy"
53+
class="max-h-[90dvh] max-w-[90vw] w-auto h-auto object-contain rounded-lg"
54+
/>
55+
</div>
56+
</figure>

src/sections/Venue.astro

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
---
2-
import { Image } from "astro:assets";
32
import Section from "@components/Section.astro";
43
import Prose from "@components/Prose.astro";
54
import Button from "@components/Button.astro";
5+
import ZoomableImage from "@components/ZoomableImage.astro";
66
import VenueContent from "@prose/venue.mdx";
77
import { event } from "@data/event";
88
import front from "@assets/venue/startgate-front.jpeg";
@@ -38,19 +38,7 @@ const venuePhotos = [
3838
{/* Mobile: swipeable scroll-snap carousel, peeking edge hints it scrolls */}
3939
<div class="flex overflow-x-auto snap-x snap-mandatory gap-4 mt-12 sm:grid sm:grid-cols-2">
4040
{venuePhotos.map((photo) => (
41-
<figure class="relative flex-none w-5/6 snap-start sm:w-full">
42-
{/* alt is empty: photo.alt is rendered once below as the visible figcaption, so it's not read twice by screen readers */}
43-
<Image
44-
src={photo.src}
45-
alt=""
46-
width={800}
47-
format="avif"
48-
class="w-full block rounded-lg object-cover aspect-4/3"
49-
/>
50-
<figcaption class="absolute inset-x-0 bottom-0 rounded-b-lg bg-linear-to-t from-black/70 to-transparent px-4 pt-10 pb-3 text-left font-mono text-xs md:text-sm text-white">
51-
{photo.alt}
52-
</figcaption>
53-
</figure>
41+
<ZoomableImage src={photo.src} alt={photo.alt} class="flex-none w-5/6 snap-start sm:w-full" />
5442
))}
5543
</div>
5644
</Section>

0 commit comments

Comments
 (0)