| 1 | type GalleryPhoto = { |
| 2 | id: string; |
| 3 | url: string; |
| 4 | caption: string | null; |
| 5 | }; |
| 6 | |
| 7 | export function PhotoGallery({ photos }: { photos: GalleryPhoto[] }) { |
| 8 | return ( |
| 9 | <ul className="grid grid-cols-2 gap-3 sm:grid-cols-3"> |
| 10 | {photos.map((p) => ( |
| 11 | <li key={p.id}> |
| 12 | <details className="group"> |
| 13 | <summary className="block cursor-pointer list-none [&::-webkit-details-marker]:hidden"> |
| 14 | <img |
| 15 | src={p.url} |
| 16 | alt={p.caption ?? "Event photo"} |
| 17 | loading="lazy" |
| 18 | className="aspect-square w-full border border-[var(--line)] object-cover transition-opacity hover:opacity-80" |
| 19 | /> |
| 20 | <span |
| 21 | aria-hidden |
| 22 | className="fixed inset-0 z-40 hidden bg-black/90 group-open:block" |
| 23 | /> |
| 24 | </summary> |
| 25 | <div className="pointer-events-none fixed inset-0 z-50 flex flex-col items-center justify-center gap-4 p-6"> |
| 26 | <img |
| 27 | src={p.url} |
| 28 | alt={p.caption ?? "Event photo"} |
| 29 | className="max-h-[80vh] max-w-full border border-[var(--line)] object-contain" |
| 30 | /> |
| 31 | {p.caption ? ( |
| 32 | <p className="serif max-w-xl text-center text-lg text-bone">{p.caption}</p> |
| 33 | ) : null} |
| 34 | <p className="kicker text-ash">Click anywhere to close</p> |
| 35 | </div> |
| 36 | </details> |
| 37 | </li> |
| 38 | ))} |
| 39 | </ul> |
| 40 | ); |
| 41 | } |