View fulldotdev/ui on GitHub

Attachment

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

Installation

npx shadcn@latest add @fulldev/attachment

Usage

import {
  Attachment,
  AttachmentAction,
  AttachmentActions,
  AttachmentContent,
  AttachmentDescription,
  AttachmentMedia,
  AttachmentTitle,
} from "@/components/ui/attachment"
<Attachment>
  <AttachmentMedia>
    <FileTextIcon />
  </AttachmentMedia>
  <AttachmentContent>
    <AttachmentTitle>sales-dashboard.pdf</AttachmentTitle>
    <AttachmentDescription>PDF · 2.4 MB</AttachmentDescription>
  </AttachmentContent>
  <AttachmentActions>
    <AttachmentAction aria-label="Remove sales-dashboard.pdf">
      <XIcon />
    </AttachmentAction>
  </AttachmentActions>
</Attachment>

Composition

Use the following composition to build an attachment:

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

Image

Set variant="image" on AttachmentMedia and render an <img> inside it.

States

Set state to reflect the upload lifecycle.

Sizes

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

Group

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

Trigger

Add an AttachmentTrigger to make the whole card open a link or dialog.

<Dialog>
  <Attachment>
    {/* media, content, actions */}
    <DialogTrigger
      render={<AttachmentTrigger aria-label="Preview research-summary.pdf" />}
    />
  </Attachment>
  <DialogContent>{/* ... */}</DialogContent>
</Dialog>

Accessibility

AttachmentAction renders a Button, and AttachmentTrigger renders a real <button> (or your element via render).

Label icon-only actions

AttachmentAction is usually icon-only, so give each one an aria-label describing the action and its target.

<AttachmentAction aria-label="Remove sales-dashboard.pdf">
  <XIcon />
</AttachmentAction>

Label the trigger

AttachmentTrigger covers the card with no text of its own, so give it an aria-label for what activating it does.

<AttachmentTrigger
  render={
    <a
      href={url}
      target="_blank"
      rel="noreferrer"
      aria-label="Open workspace.png"
    />
  }
/>

Keyboard scrolling

An AttachmentGroup scrolls horizontally.

Meaning beyond color

The error state uses a destructive color.

API Reference

Source: react/src/components/ui/attachment.tsx

Attachment

The root attachment container.

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.
classNamestring-Additional classes to apply to the root element.

AttachmentMedia

The media slot for an icon or image preview.

PropTypeDefaultDescription
variant"icon" | "image""icon"Whether the media holds an icon or an <img>.
classNamestring-Additional classes to apply to the media slot.

AttachmentContent

Wraps the title and description.

PropTypeDefaultDescription
classNamestring-Additional classes to apply to the content slot.

AttachmentTitle

The attachment name.

PropTypeDefaultDescription
classNamestring-Additional classes to apply to the title.

AttachmentDescription

Secondary metadata such as the file type, size, or upload status.

PropTypeDefaultDescription
classNamestring-Additional classes to apply to the description.

AttachmentActions

A container for one or more actions, aligned to the end of the attachment.

PropTypeDefaultDescription
classNamestring-Additional classes to apply to the actions.

AttachmentAction

An action button.

PropTypeDefaultDescription
sizeButton["size"]"icon-xs"The button size.
...propsReact.ComponentProps<typeof Button>-Props spread to the underlying Button.

AttachmentTrigger

A full-card overlay that activates the attachment.

PropTypeDefaultDescription
renderReactElement | function-Render as a different element, such as a link.
...propsReact.ComponentProps<"button">-Props spread to the trigger element.

AttachmentGroup

Lays out attachments in a horizontally scrollable, snapping row.

PropTypeDefaultDescription
classNamestring-Additional classes to apply to the group.