OPERATOR

AttachmentPreview

Preview content

Supply metadata separately from the preview. Plain text remains escaped; unsupported content retains a readable explanation and the file's identity.

Equipment CSV preview

Equipment.csv

66 bytes · text/csv

id,name,kind,site
EQ-101,Pump Alpha,pump,west
EQ-102,Fan Bravo,fan,east

Document attachment

Inspection.pdf

4096 bytes · application/pdf

No inline preview for this document. Open it through your application's attachment workflow.

<AttachmentPreview
  label="Equipment file"
  attachment={{ id: "file-1", name: "Equipment.csv", sizeBytes: 1024, mediaType: "text/csv" }}
  preview={{ kind: "text", text: csvPreview }}
  onDownload={requestDownload}
/>

AttachmentMetadata has id, name, sizeBytes, and optional mediaType. The component performs no file reads. AttachmentPreviewContent selects one representation:

  • { kind: "text", text }: an escaped, keyboard-scrollable text preview. At most 16,384 characters are displayed; longer values receive a truncation notice.
  • { kind: "image", src, alt }: a supplied image source and alternative text. Relative URLs, HTTP/HTTPS, blob URLs and base64 PNG/JPEG/GIF/WebP/AVIF/BMP data URLs are accepted. An unsupported source or decoding failure produces readable feedback. Changing attachment identity or source retires an earlier image failure.
  • { kind: "unavailable", message }: an application explanation for unsupported or unavailable content.

An image or text preview is at most 60% of the window's height by default; the text scrolls inside its region and an image keeps its proportions. A host that knows its own space sets the cap with the --oprt-preview-max-height custom property on the preview, for example className="[--oprt-preview-max-height:24rem]" in a side panel.

HTML, scripts, SVG markup and document iframes are not rendered. The caller chooses an appropriate representation, bounds the content read before passing it, and owns browser object URLs. Create those URLs after a user interaction or mount; revoke them when replaced or no longer used. No object URLs are created during server rendering.

Actions and identity

onDownload(id) and onRemove(id) expose only supplied actions. Activation does not imply a completed download or remove the preview. Keep the attachment ID stable across updates to the same file. If the application removes the entire preview, it must move focus to an appropriate surviving control. disabled prevents both requests while preserving content.

Props

PROPTYPEDEFAULTREQUIRED
labelstring—yes
attachment

AttachmentMetadata object: stable id, name, sizeBytes, optional mediaType. No file reads or persistence are performed.

node—yes
preview

AttachmentPreviewContent: {kind:'image',src,alt}, {kind:'text',text} or {kind:'unavailable',message}. Text is escaped and limited to 16,384 displayed characters. Images permit relative/http/https/blob sources and base64 PNG/JPEG/GIF/WebP/AVIF/BMP data URLs; decoding failures remain readable. No HTML or document iframe rendering.

node—yes
disabled

Disables download/remove actions while preserving the preview.

booleanfalseno
onDownload

Requests a download by attachment ID. Invocation does not prove a file was saved.

function—no
onRemove

Requests removal by attachment ID. The caller owns replacement and focus if removing the entire preview.

function—no
className

Classes for the root. Set --oprt-preview-max-height here to change the image and text preview cap from its 60vh default, for example [--oprt-preview-max-height:24rem].

string—no

The forwarded ref targets the root div. Native div attributes are supported, and the visible label names the region. Metadata and preview are typed object props; they are described under node in the manifest's available schema.

Accessibility

  • Each preview is a named region with readable filename, byte count and optional media type. The byte count is shown in full and stays on one line with its unit.
  • Image alternative text is required. Decode errors remain visible and announce a status change.
  • Text retains case and whitespace, uses Mono for source content, and exposes a named scroll region with a focus indicator.
  • Download and Remove buttons include the filename in their accessible names and support keyboard activation.
  • Long or unbroken labels, filenames, media types, messages and text wrap, breaking anywhere when they must, without erasing their meaningful content.

Manifest entry

<AttachmentPreview label="Equipment file" attachment={attachment} preview={{kind:"text",text:csvPreview}} onDownload={requestDownload} />
View agent manifest
{
  "description": "Named attachment metadata with an escaped text preview, safe image source or readable fallback.",
  "props": {
    "label": {
      "type": "string",
      "required": true
    },
    "attachment": {
      "type": "node",
      "required": true,
      "description": "AttachmentMetadata object: stable id, name, sizeBytes, optional mediaType. No file reads or persistence are performed."
    },
    "preview": {
      "type": "node",
      "required": true,
      "description": "AttachmentPreviewContent: {kind:'image',src,alt}, {kind:'text',text} or {kind:'unavailable',message}. Text is escaped and limited to 16,384 displayed characters. Images permit relative/http/https/blob sources and base64 PNG/JPEG/GIF/WebP/AVIF/BMP data URLs; decoding failures remain readable. No HTML or document iframe rendering."
    },
    "disabled": {
      "type": "boolean",
      "default": false,
      "description": "Disables download/remove actions while preserving the preview."
    },
    "onDownload": {
      "type": "function",
      "description": "Requests a download by attachment ID. Invocation does not prove a file was saved."
    },
    "onRemove": {
      "type": "function",
      "description": "Requests removal by attachment ID. The caller owns replacement and focus if removing the entire preview."
    },
    "className": {
      "type": "string",
      "description": "Classes for the root. Set --oprt-preview-max-height here to change the image and text preview cap from its 60vh default, for example [--oprt-preview-max-height:24rem]."
    }
  },
  "composable_with": [
    "FileUpload",
    "UploadQueue",
    "Dialog"
  ],
  "never_inside": [
    "Button"
  ],
  "example": "<AttachmentPreview label=\"Equipment file\" attachment={attachment} preview={{kind:\"text\",text:csvPreview}} onDownload={requestDownload} />"
}

On this page