Skip to content

WEBDEV-9022: Migrate the image viewer into elements - #93

Open
jbuckner wants to merge 9 commits into
mainfrom
WEBDEV-9022-migrate-image-viewer
Open

WEBDEV-9022: Migrate the image viewer into elements#93
jbuckner wants to merge 9 commits into
mainfrom
WEBDEV-9022-migrate-image-viewer

Conversation

@jbuckner

@jbuckner jbuckner commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator

Ports offshoot's image viewer in as ia-image-viewer, split into a slide element, a controls element, and a reactive controller for touch/wheel/keyboard. Sub-elements are namespaced ia-imgview-* so they can't collide with offshoot's copy, which still registers image-viewer verbatim.

No dependencies added. It took metadata-service File objects and an ItemDetails only to build download URLs, so it now takes a plain { name, url, title? } list. It also called history.replaceState and reached for offshoot's analytics handler; those are events now (imageChanged, imageLoaded, imageLoadFailed), so the host decides.

Reduced motion moves from CSS to JS, which fixes two bugs it was hiding: animation: none on the wrap glow meant animationend never fired, so the glow sat at full opacity forever, and the swipe settle set its transition inline from JS where the media query couldn't reach it. Navigation now lands immediately with nothing to wait on.

Also folds in WEBDEV-9023: the image link is a real anchor rather than a role="link" div, the nav labels go through msg(), and a live region announces the image as it changes.

Offshoot swaps over in WEBDEV-9024, against a prerelease of this.

🤖 Generated with Claude Code

https://claude.ai/code/session_01BmPnn4m5EKaMYPjNvWqpJp

Ports offshoot's image viewer in as ia-image-viewer, split up on the way:
a slide element owning one image's load and failed state, a controls element
for the buttons and counter, and a reactive controller for touch, wheel and
keyboard. Sub-elements are namespaced ia-imgview-* so they can't collide with
offshoot's copy, which registers image-viewer verbatim and would throw on a
second registration.

No dependencies added. The viewer read metadata-service File objects and an
ItemDetails only to build download URLs, so it now takes a plain
{ name, url, title? } list and metadata-service is gone. It also called
history.replaceState and reached for offshoot's analytics handler directly;
both are events now (imageChanged, imageLoaded, imageLoadFailed), so the host
decides what to do with them. Picking which IA derivatives to show stays in
offshoot, where it belongs.

Reduced motion is driven from JS rather than CSS. The old
@media (prefers-reduced-motion) block set animation: none on the wrap glow,
which meant animationend never fired and the glow sat there at full opacity
forever; the swipe settle set its transition inline from JS, which the media
query couldn't reach at all. Navigation now lands immediately with no
animation to wait on, and the glow never shows.

Accessibility: the image link is a real anchor instead of a role="link" div,
so middle-click and open-in-new-tab work, the nav button labels go through
msg(), and a live region announces the image as it changes.

Theming runs through --image-viewer-* knobs. The breakpoint that throws the
nav buttons over the image is a named container query, so it tracks the
viewer's own width rather than whichever container a consumer has further up.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BmPnn4m5EKaMYPjNvWqpJp
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
PR Preview Action v1.8.1

🚀 View preview at
https://internetarchive.github.io/elements/pr/pr-93/

Built to branch ghpages at 2026-09-04 21:16 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

@codecov-commenter

codecov-commenter commented Sep 4, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.00000% with 60 lines in your changes missing coverage. Please review.
✅ Project coverage is 84.53%. Comparing base (d6888bb) to head (a692941).

Files with missing lines Patch % Lines
.../elements/ia-image-viewer/image-viewer-gestures.ts 77.77% 22 Missing and 10 partials ⚠️
src/elements/ia-image-viewer/ia-image-viewer.ts 90.29% 2 Missing and 11 partials ⚠️
.../elements/ia-image-viewer/ia-image-viewer-story.ts 73.68% 3 Missing and 2 partials ⚠️
...ments/ia-image-viewer/image-viewer.test-helpers.ts 86.11% 0 Missing and 5 partials ⚠️
src/elements/ia-image-viewer/ia-imgview-slide.ts 87.87% 0 Missing and 4 partials ⚠️
src/util/prefers-reduced-motion.ts 50.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #93      +/-   ##
==========================================
- Coverage   84.69%   84.53%   -0.16%     
==========================================
  Files          38       45       +7     
  Lines        1274     1649     +375     
  Branches      303      394      +91     
==========================================
+ Hits         1079     1394     +315     
- Misses        115      142      +27     
- Partials       80      113      +33     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

jbuckner and others added 8 commits September 4, 2026 11:43
…test

Offshoot's image-viewer is being deleted outright in WEBDEV-9024, not left
running alongside this one, so there's no migration window where a second
registration of those names could throw. The test still keeps the parts
namespaced and off generic names, which is the part that outlives the port.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BmPnn4m5EKaMYPjNvWqpJp
Six of the seven elements already here don't declare them, so this was
following the newest addition rather than the repo. tsc only ever needed two
of the three, and only at three call sites, which now say what they are
locally instead.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BmPnn4m5EKaMYPjNvWqpJp
The viewer reset to the first image whenever the images property changed,
including when the array was a new reference holding the same images. A host
that builds its list in a getter does that on every render, so navigating
anywhere snapped straight back to the start.

It now holds its place by name and only returns to the start when the image it
was showing is really gone. An explicit currentImageName still wins, since
that's the host asking for a particular image rather than just re-rendering.

The demo built its list in a getter, which is how this showed up: with a
broken image in the set the event log updated constantly, so the list churned
constantly. Those sets are built once now.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BmPnn4m5EKaMYPjNvWqpJp
Height and max-width were custom properties, which is the one thing plain CSS
on the element already does — a rule in the outer tree beats the :host
default, so a host just writes `ia-image-viewer { height: 400px }`. The demo
also set the height property on the element wrapping the viewer, which sat
closer than the style controls and quietly shadowed them.

Takes the rest of the knobs down with them. Seven of the ten were invented for
completeness and nothing set them; the three left are the ones a consumer
can't reach any other way, and are the three the demo actually exercises.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BmPnn4m5EKaMYPjNvWqpJp
Two screenshots from a failing run got committed with the last change. Vitest
writes them next to __screenshots__, which is already ignored here, so this
just covers the other half. Offshoot ignores both.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BmPnn4m5EKaMYPjNvWqpJp
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants