feat(web-ui): open image attachments in a gallery viewer - #964
Open
time-attack wants to merge 1 commit into
Open
feat(web-ui): open image attachments in a gallery viewer#964time-attack wants to merge 1 commit into
time-attack wants to merge 1 commit into
Conversation
Clicking an image in a chat message used to open the raw artifact URL in a new tab, which is a dead end when a message carries several pictures. Images now open in a full-screen modal viewer scoped to the message: prev/next arrows, arrow-key, Home/End and swipe navigation, a filmstrip of thumbnails, an n / m counter, download and open-original links, click-to-zoom to natural size, and Escape or backdrop click to close with focus returned to the tile that opened it. The composer attachment strip shows a thumbnail for each image attachment and opens the same viewer so uploads can be checked before sending. Messages with more than one image render as square cover tiles instead of a row of variably sized previews.
time-attack
force-pushed
the
multi-image-lightbox-viewer
branch
from
September 7, 2026 03:31
935502b to
3f058d9
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Clicking an image attachment in a chat message used to open the raw artifact URL in a new tab, which is a dead end when someone uploads several pictures at once. This adds a proper gallery viewer to the web UI.
←/→,Home/End, and touch swipe (on the image stage only) move between images; navigation wraps.n / mcounter, a zoom toggle, Download, Open original (when the image is a stored artifact), and Close.Esc, the Close button, or clicking the empty backdrop closes and returns focus to the tile that opened the viewer. Escape is trapped at the dialog so it no longer reaches the page-level handlers (split-pane un-maximise, sidebar selection clear).role="status"announces "Image 2 of 3: name.png" on every navigation; all controls are labelled and keyboard reachable.Implementation: one new module
plugins/web-ui/src/lightbox.ts(native<dialog>+showModal(), single document-level host like the search palette),chat.tsroutes both user attachments and delivered files through onemessageFileshelper that builds the gallery, and the duplicated data-URL construction moved toinlineImageSrcinui.ts.Behaviour change to note: transcript image tiles are now
<button>s instead of<a target="_blank">, so cmd/middle-click to a new tab no longer works on the tile itself. "Open original" inside the viewer covers that case.Demo
Screenshots from the dev instance (Firefox-equivalent Chromium via Aside, real Pi turn, local Postgres):
Verification
plugins/web-ui: typecheck (all three tsconfigs), eslint, prettier clean.test/lightbox.test.ts(jsdom via vitessrLoadModule): open state and links, arrow-key wrap, Home/End, arrow buttons and filmstrip, swipe vs tap vs zoomed pan, single-image mode, Escape containment and focus restore, backdrop vs image click, index clamping.renderable-image-source.test.tsupdated for the new chip structure.dev-instance(--no-slack): pasted three PNGs, checked composer thumbnails and preview, sent, verified tiles, viewer navigation, zoom focus point, Escape not reaching document listeners, and the reload-from-history path where tiles and links come from/api/files/:id/content.trapDialogFocus), long filenames blowing out the grid on narrow viewports (grid-template-columns: minmax(0, 1fr)), pointer-only zoom (header zoom button), stale zoomable state on resize, live-region wording, 44px header tap targets under 640px,color-scheme: darkscrollbars, transparent tile background.Need help on this PR? Tag
@codesmith-botwith what you need. Autofix is disabled.