src/lib/Gallery.svelte opens a native <dialog> with showModal(). The browser closes it on Escape, but the component only tears down its state in its own close(), which is wired to backdrop clicks.

Current State

  • No onclose/oncancel handler on the dialog: after Escape, dialogOpen stays true, selectedIndex keeps its value, the observer and the scroll listener are never removed, preload links stay in <head>
  • Because dialogOpen is stuck, the thumbnail never gets its view-transition-name back; the next open animates from the wrong element
  • Prev/next buttons have tabindex="-1" and there is no keydown handler, so arrow keys do nothing
  • The scroll-to-close listener fires on the layout shift caused by opening on some mobile browsers

Tasks

  • Handle oncancel (preventDefault, call close()) or run the cleanup from onclose
  • Add ArrowLeft/ArrowRight/Home/End handling on the dialog
  • Make the nav buttons focusable and move focus back to the opening thumbnail on close
  • Add a component test: open, press Escape, assert listeners and state are reset

Keyboard-friendly gallery

Escape, arrows, focus

A static site template built with SvelteKit.

Sveleton, 2025