Attachment
Displays a file or image attachment with media, metadata, upload state, and actions.
Installation
Preview
Features
- Icon and image media through
AttachmentMedia - Upload states:
idle,uploading,processing,error, anddonewith built-in styling and a shimmer while in progress - Three sizes and horizontal or vertical orientation
- A full-card
AttachmentTriggerthat opens a link or dialog while the actions stay independently clickable - Scrollable, snapping
AttachmentGroupwith an edge fade - Customizable styling through the
classNameprop on every part
Examples
Image
Set variant="image" on AttachmentMedia and render an <img> inside it. Use orientation="vertical" to stack the media above the content.
States
Set state to reflect the upload lifecycle. uploading and processing shimmer the title, and error switches to a destructive treatment.
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. It fills the card behind the actions, so the actions stay clickable.
<Dialog>
<Attachment>
{/* media, content, actions */}
<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 asChild). Follow the guidance below so both are operable and announced.
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
href={url}
target="_blank"
rel="noreferrer"
aria-label="Open workspace.png"
/>The trigger sits behind the actions in the stacking order, so an AttachmentAction and the AttachmentTrigger never trap each other — both remain separately focusable and clickable.
Keyboard scrolling
An AttachmentGroup scrolls horizontally. When its attachments are interactive: a trigger or actions, keyboard users reach off-screen items by tabbing to them. For a row of presentational attachments, make the group itself focusable and scrollable by adding tabIndex={0}, role="group", and an aria-label.
Meaning beyond color
The error state uses a destructive color. Keep the failure reason in AttachmentDescription so the state is not conveyed by color alone.
API Reference
Attachment
The root attachment container.
| Prop | Type | Default | Description |
|---|---|---|---|
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. |
className | string | - | Additional classes to apply to the root element. |
AttachmentMedia
The media slot for an icon or image preview.
| Prop | Type | Default | Description |
|---|---|---|---|
variant | "icon" | "image" | "icon" | Whether the media holds an icon or an <img>. |
className | string | - | Additional classes to apply to the media slot. |
AttachmentContent
Wraps the title and description.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional classes to apply to the content slot. |
AttachmentTitle
The attachment name. Shimmers while the attachment is uploading or processing.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional classes to apply to the title. |
AttachmentDescription
Secondary metadata such as the file type, size, or upload status.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional classes to apply to the description. |
AttachmentActions
A container for one or more actions, aligned to the end of the attachment.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional classes to apply to the actions. |
AttachmentAction
An action button. Renders a Button and accepts all of its props.
| Prop | Type | Default | Description |
|---|---|---|---|
size | Button["size"] | "icon-xs" | The button size. |
...props | React.ComponentProps<typeof Button> | - | Props spread to the underlying Button. |
AttachmentTrigger
A full-card overlay that activates the attachment. Renders a <button> by default.
| Prop | Type | Default | Description |
|---|---|---|---|
...props | React.ComponentProps<"button"> | - | Props spread to the trigger element. |
AttachmentGroup
Lays out attachments in a horizontally scrollable, snapping row.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Additional classes to apply to the group. |