Attachments tray

Files on their way into a chat: a tray above the input with progress and retry, a drop zone that checks what it accepts, a grid of images to reorder, files weighed against the context limit, and how they look once sent.

Loading preview…

Install

  1. 1

    Run this command in your Tailwind CSS project. It adds components/ai/attachments-tray-default.tsx and installs its dependencies.

    $ npx shadcn@latest add https://gradientdeck.com/ai-components/r/attachments-tray-default.json

Usage & API

Example

attachments-tray-default.tsx
import { Scene } from "@/components/ai/attachments-tray-default"

<Scene
  scene={scene}
  uid="…"
/>

Props Scene

PropType & descriptionRequired
sceneTrayItem["scene"]Required
uidstringRequired

Dependencies

  • React
  • Tailwind CSS
  • motion
  • lucide-react
Implementation notes

Above the input exports AttachmentsTray. An item has id, name, kind of image, pdf, sheet or doc, size, optional pages, progress, optional error, and an optional scene of kitchen, floorplan or hallway for drawn image previews. Callbacks are onRemove, onRetry and onOpen. Images are square tiles. The button name is Preview plus the name when the upload is done, the name plus uploading and the percent while progress is under 1, or the name plus upload failed when error is set. A failed image shows Retry on the tile. Other files show a type label, PDF, DOCX or XLSX, then pages or sheets, then size, or Uploading and the percent, or the error string beside a Retry text button. Remove is a small button labelled Remove plus the name. The demo opens a preview dialog labelled with the file name and a Close preview button, and Escape closes it. The field placeholder is Ask about these files.

Choosing a layout

Use Above the input for a normal chat attach flow: photos, PDFs and sheets, with upload percent and a retry. The demo blocks send while any item is still uploading and has no error, and the button name becomes Send, waiting for uploads. A live line says Uploading, or 1 file didn't upload. Use Drop zone when people drag from the desktop and you must say no to a video or an installer. The overlay copy is Drop to attach, and PDF, DOCX, CSV, XLSX, PNG or JPG, up to 30 MB each. txt and md are accepted by checkFile even though that sentence does not name them. Use Image grid for a visual edit, where order and a reference shot matter. The demo caps the set at 10.

Use Context budget before a send that might blow the window, especially when a report should contribute a page range rather than the whole file. Context meter is the quieter summary of a conversation that is already in the window. It has no include switch and no page dialog. Use In a sent message once the files belong to a bubble. The viewer is a dialog with previous and next attachment, and PDFs also get previous and next page. Do not keep the upload tray mounted after send if the message variant is now the source of truth.

The drop overlay says JPG, but a markdown file still attaches. Which rule wins?

checkFile wins if you use it. ACCEPTED includes txt and md, and also jpeg, which the overlay sentence does not list. The overlay is copy in the demo, not a second validator. A rejection message is whatever checkFile returned, shown in the alert until onDismiss. If you want the sentence and the check to match, change the copy. The function will still refuse an extension that is not in the list, and anything over 30 MB.

Does marking a reference image change the prompt?

No. onToggleReference only tells you the id. The grid stores reference on the image you pass back in. The demo counts how many are marked and prints that next to the field, including the singular reference. Describe the edit is a separate textarea. When you submit, read both the text and the images array, and treat reference as your own signal for which shot the edit should follow. Remove and reorder are also callbacks. The grid does not upload and does not call a model.