Add swipe navigation to the photo detail page

Swipe left for older, right for newer, matching the existing arrow keys.
The image tracks the finger and slides out on commit; the exit animation
covers the page load, so this stays plain static-site navigation.

The keyboard handler moves out of the template into static/photo-nav.js,
which the existing //go:embed of static/ picks up with no generator
changes.

Swipes starting within 24px of a screen edge are left alone — that strip
is the browser's own back-gesture. Only touch pointers are handled, so
desktop drag-to-save still works, and the axis locks after 10px so
vertical drags stay scrolls. With no neighbour that way the image
rubber-bands instead of navigating.

Also prefetch the neighbour medium JPEGs, not just their HTML, or the
next page still blocks on a fresh image request.

The keyboard handler now bails on modifier keys; it previously hijacked
Alt+ArrowLeft, which is browser-back on Linux and Windows.
This commit is contained in:
2026-08-19 23:24:42 +02:00
parent 210ce69e18
commit 15822ed227
3 changed files with 225 additions and 13 deletions
+27
View File
@@ -248,6 +248,33 @@ body {
height: auto;
}
/* Swipe navigation. pan-y claims the horizontal axis for the gesture handler
while leaving vertical scrolling native. will-change is scoped to the two
transient states so the image is not permanently promoted to its own layer. */
.dimg-wrap {
touch-action: pan-y;
}
.dimg-wrap.dragging {
user-select: none;
-webkit-user-select: none;
}
.dimg-wrap.dragging img {
transition: none;
will-change: transform;
}
.dimg-wrap.animating img {
transition: transform 180ms ease-out, opacity 180ms ease-out;
will-change: transform;
}
@media (prefers-reduced-motion: reduce) {
.dimg-wrap.animating img { transition: none; }
}
.dsidebar {
width: 220px;
flex-shrink: 0;