Attachment

A file or image attachment with media, metadata, upload state, and actions.

PDF
feed-in-report.pdfPDF · 2.4 MB

The Attachment component displays a file or image attachment: its media, name, and metadata, with optional actions and upload state. Use it for files and images in chat composers, message threads, and upload lists.

Usage

import {
  Attachment,
  AttachmentAction,
  AttachmentActions,
  AttachmentContent,
  AttachmentDescription,
  AttachmentMedia,
  AttachmentTitle,
} from '@epilot/spark-ui/attachment'
<Attachment>
  <AttachmentMedia>
    <MaterialSymbol name="content_copy" />
  </AttachmentMedia>
  <AttachmentContent>
    <AttachmentTitle>feed-in-report.pdf</AttachmentTitle>
    <AttachmentDescription>PDF · 2.4 MB</AttachmentDescription>
  </AttachmentContent>
  <AttachmentActions>
    <AttachmentAction aria-label="Remove feed-in-report.pdf">
      <MaterialSymbol name="close" />
    </AttachmentAction>
  </AttachmentActions>
</Attachment>

Composition

Attachment
├── AttachmentMedia
├── AttachmentContent
│   ├── AttachmentTitle
│   └── AttachmentDescription
├── AttachmentActions
│   └── AttachmentAction
└── AttachmentTrigger

Use AttachmentGroup to lay out multiple attachments in a scrollable row.

Examples

Image

Set variant="image" on AttachmentMedia and render an <img> inside it. Use orientation="vertical" to stack the media above the content.

Roof survey
roof-survey.pngPNG · 1.1 MB

States

Set state to reflect the upload lifecycle. uploading and processing shimmer the title, and error switches to a destructive treatment.

PDF
consumption-2024.csvUploading… 40%
CSV
consumption-2024.csvUpload failed: retry
CSV
consumption-2024.csvCSV · 84 KB

Sizes

Use size to switch between default, sm, and xs.

PDF
invoice.pdfPDF · 320 KB
PDF
invoice.pdfPDF · 320 KB
PDF
invoice.pdfPDF · 320 KB

Group

Wrap attachments in AttachmentGroup to lay them out in a horizontally scrollable, snapping row with an edge fade.

PDF
feed-in.pdfAttached
CSV
meter.csvAttached
PNG
roof.pngAttached
PDF
tariff.pdfAttached

Trigger

Add an AttachmentTrigger to make the whole card open a link or dialog. It fills the card behind the actions, so the actions stay clickable. Pass render to swap in a link or a dialog trigger.

<Attachment>
  {/* media, content, actions */}
  <AttachmentTrigger
    render={
      <a
        href={url}
        target="_blank"
        rel="noreferrer"
        aria-label="Open workspace.png"
      />
    }
  />
</Attachment>

Accessibility

  • Label icon-only actions. AttachmentAction is usually icon-only, so give each one an aria-label describing the action and its target.
  • Label the trigger. AttachmentTrigger covers the card with no text of its own, so give it an aria-label for what activating it does. It sits behind the actions in the stacking order, so both stay separately focusable.
  • Meaning beyond color. The error state uses a destructive color; keep the failure reason in AttachmentDescription.

API Reference

Attachment

PropTypeDefaultDescription
state'idle' | 'uploading' | 'processing' | 'error' | 'done''done'The upload state. Drives styling and the shimmer.
size'default' | 'sm' | 'xs''default'The attachment size.
orientation'horizontal' | 'vertical''horizontal'Lay the media beside or above the content.
classNamestringAdditional classes.

AttachmentMedia

PropTypeDefaultDescription
variant'icon' | 'image''icon'Whether the media holds an icon or an <img>.
classNamestringAdditional classes.

AttachmentAction

Renders a Spark Button and accepts all of its props. Defaults to styleVariant="ghost", color="neutral", size="icon-small".

AttachmentTrigger

A full-card overlay that activates the attachment. Renders a <button> by default; pass render to render a link or a dialog trigger.

AttachmentContent / AttachmentTitle / AttachmentDescription / AttachmentActions / AttachmentGroup

PropTypeDefaultDescription
classNamestringAdditional classes to apply to the part.

AttachmentTitle shimmers while the attachment is uploading or processing. AttachmentGroup lays attachments out in a horizontally scrollable, snapping row with an edge fade.

On this page