description, kind
| description | kind |
|---|---|
| Attachment presentation for the conversation UI: mixed draft-attachment rail, document drop target, history-image gallery, and original-image lightbox; for users and maintainers of the Web attachment experience. | package-reference |
@deepseek-ai/dsh-client-ui-attachment
English | 中文
Summary
This package renders everything the conversation UI shows about attachments: one ordered draft rail under the composer, a full-viewport drop invitation, durable images in Chat, Trajectory, and Tool results, and a lightbox for the original image. Attachment data, upload state, image loading, and callbacks come from the declared slot owners. Choose it for the DeepSeek Chat-style attachment experience.
Table of Contents
- Use this package
- Understand the implementation
- Further Exploration
- Model Experience
- Known Limitations and Deferred Work
- Dev Note
Use this package
Image drag actions and the composer’s original-file reader arrive through slot injection from ui-file-drag. The image gallery Factory also receives these actions through its declared inject face; custom Factory replacements must supply that face.
Mount this plugin alongside ui-conversation and ui-tool when tool results need an image gallery. It waits for their slot declarations and registers its components into them. Users then see the mixed draft-attachment rail, DeepSeek Web file cards with upload controls, the drop overlay with its limits line, message images sized by count, the tool card's gallery, and the Escape/mask/close lightbox.
Draft attachments
Images and generic files retain pick order in one non-wrapping horizontal rail. Every item is 64px high: an image is a 64px square thumbnail, while a generic file is a 240px-wide DeepSeek Web card with a 16px radius, blue gradient document glyph, filename, and uppercase extension plus byte size. Edge arrows page hidden overflow, the scrollbar stays hidden, and a newly added item is revealed at the rail's end. Uploading replaces a file glyph with a spinner and shows byte progress when the carrier reports it, with an indeterminate bar before the first report; failure shows retry, and removal controls appear on hover or keyboard focus while remaining visible on touch devices. An uploading image shows the same progress bar along its thumbnail's bottom edge, and a failed image upload turns the thumbnail into its retry control, except an image the Host refused, whose thumbnail explains the refusal in a tooltip that a tap or click also pins and leaves removal as the way out. Clicking an image opens the original.
Message images and the lightbox
In Chat, one user message presents files and images in a right-aligned wrapping flow that preserves source order. A lone image without another attachment renders at 240px on its longer edge (aspect clamped to [0.25, 4], never upscaled); when the message has more than one attachment, each image is a fixed 64px square beside 240×64px file cards. A loaded image opens the document-level lightbox on click; a failed load shows a retry control instead. The lightbox closes on Escape, a mask press, or its close control, and restores focus to its opener.
Trajectory attachment rows request 48px square thumbnails that contain the complete image without cropping. Loading and retry icons keep the same box, with localized tooltips and accessible names; the image opens the same lightbox. A slot owner may supply a presentation-only image label for the thumbnail and lightbox without changing the durable reference or the cache lookup.
Loaded conversation images can be dragged into the composer as image attachments or to another application as original files. Dragging does not open the lightbox. The shared image-transfer owner retains Web drag bytes until the gesture ends; Desktop uses the system file drag. A failed preparation or drag keeps the image visible and reports a localized retry message.
Internal Web image drags do not show the full-page overlay. A foreign or expired image token without actual files is ignored. Browser transfer limitations are documented by ui-primitives.
Drop overlay
While an external file drag is over the page, the full-viewport overlay announces the drop: illustration, title, and a limits line when drops are accepted. The overlay only shows state — the owner's document-level listeners decide accept or reject, and the drop handler reports which dropped members are directories through the entry API so the owner can cite or refuse them.
Understand the implementation
Implementation internals — click to expand
The plugin provides the root-scoped conversation.images.content Factory. Its official MessageImages entries fill conversation.chat.user.images, conversation.chat.message.images, conversation.trajectory.images, and tool.call.images at priority 100 through ctx.slots.inject. A lower-priority entry replaces only its own position; removing it restores the official entry. All defaults reuse one gallery with explicit image references, authorized loader, layout hints, and optional complete labels. The Factory owns gallery presentation and default copy, not Session state or read authorization. Each domain owns its Slot declaration. The composer attachment rail remains a separate entry, and the package entry exports no components.
| File | Role |
|---|---|
src/client/ComposerAttachments.tsx |
Ordered image/file rail + drop overlay assembly |
src/client/drop-events.ts |
Document drag-and-drop listeners installed by each mounted attachment view's effect |
src/AttachmentRail.tsx |
Horizontal attachment overflow, wheel translation, edge arrows |
src/client/MessageImages.tsx |
Per-message gallery + lightbox assembly |
src/MessageImage.tsx |
Single image sizing, load/retry, click-to-open; local submission-echo previews render their object URL directly |
ImageLightbox |
Document-level modal preview over the shared mask |
src/DropOverlay.tsx |
Pointer-inert drag invitation portal |
Further Exploration
Read these pages when the attachment surface is not enough. They move from the slots this package fills to the conversation shell that owns the input flow.
- ui-conversation — declares the attachment slots and owns the composer and image intake.
- Web client architecture — how browser plugin rows load and register slots.
- Client package map — adjacent browser UI packages.
Model Experience
None, as the plugin only renders attachment state supplied by the conversation UI and contributes no model-visible input.
KV Cache effect
None; this package neither assembles nor sends a provider request.
Known Limitations and Deferred Work
These limits define the current attachment surface. They are package constraints, not a general image-viewer comparison or a task backlog.
- No zoom or download in the lightbox — the preview renders the original at fit-to-viewport size only.
- The lightbox does not trap focus — it sets
aria-modaland restores focus on close, but Tab can reach the page behind it.
Dev Note
Working context for maintainers — click to expand
None.