Displays a file or image attachment with media, metadata, upload state, and actions.
Epicenter
Local-first, open source apps
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.
Installation
Install the required shadcn-svelte dependencies:
Copy and paste the following code into your project.
Usage
<script lang="ts">
import * as Attachment from "$lib/components/ui/attachment/index.js";
</script> <Attachment.Root>
<Attachment.Media>
<FileTextIcon />
</Attachment.Media>
<Attachment.Content>
<Attachment.Title>sales-dashboard.pdf</Attachment.Title>
<Attachment.Description>PDF · 2.4 MB</Attachment.Description>
</Attachment.Content>
<Attachment.Actions>
<Attachment.Action aria-label="Remove sales-dashboard.pdf">
<XIcon />
</Attachment.Action>
</Attachment.Actions>
</Attachment.Root> Composition
Use the following composition to build an attachment:
Attachment.Root
├── Attachment.Media
├── Attachment.Content
│ ├── Attachment.Title
│ └── Attachment.Description
├── Attachment.Actions
│ └── Attachment.Action
└── Attachment.Trigger Use Attachment.Group to lay out multiple attachments in a scrollable row:
Attachment.Group
├── Attachment.Root
└── Attachment.Root Features
- Icon and image media through
Attachment.Media - 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
Attachment.Triggerthat opens a link or dialog while the actions stay independently clickable - Scrollable, snapping
Attachment.Groupwith an edge fade - Customizable styling through the
classprop on every part
Image
Set variant="image" on Attachment.Media 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 Attachment.Group to lay them out in a horizontally scrollable, snapping row with an edge fade.
Trigger
Add an Attachment.Trigger to make the whole card open a link or dialog. It fills the card behind the actions, so the actions stay clickable.
<Dialog.Root>
<Attachment.Root>
<!-- media, content, actions -->
<Dialog.Trigger>
{#snippet child({ props })}
<Attachment.Trigger
aria-label="Preview research-summary.pdf"
{...props}
/>
{/snippet}
</Dialog.Trigger>
</Attachment.Root>
<Dialog.Content><!-- ... --></Dialog.Content>
</Dialog.Root> Accessibility
Attachment.Action renders a Button, and Attachment.Trigger renders a real <button> (or your element via the child snippet). Follow the guidance below so both are operable and announced.
Label icon-only actions
Attachment.Action is usually icon-only, so give each one an aria-label describing the action and its target.
<Attachment.Action aria-label="Remove sales-dashboard.pdf">
<XIcon />
</Attachment.Action> Label the trigger
Attachment.Trigger covers the card with no text of its own, so give it an aria-label for what activating it does.
<Attachment.Trigger>
{#snippet child({ props })}
<a
href={url}
target="_blank"
rel="noreferrer"
aria-label="Open workspace.png"
{...props}
></a>
{/snippet}
</Attachment.Trigger> The trigger sits behind the actions in the stacking order, so an Attachment.Action and the Attachment.Trigger never trap each other. Both remain separately focusable and clickable.
Keyboard scrolling
An Attachment.Group 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 Attachment.Description so the state is not conveyed by color alone.
API Reference
Attachment
The root attachment container.
Attachment.Media
The media slot for an icon or image preview.
Attachment.Content
Wraps the title and description.
Attachment.Title
The attachment name. Shimmers while the attachment is uploading or processing.
Attachment.Description
Secondary metadata such as the file type, size, or upload status.
Attachment.Actions
A container for one or more actions, aligned to the end of the attachment.
Attachment.Action
An action button. Renders a Button and accepts all of its props.
Attachment.Trigger
A full-card overlay that activates the attachment. Renders a <button> by default.
Attachment.Group
Lays out attachments in a horizontally scrollable, snapping row.