elements
Demos UI Feed Discuss Install
Style System
  • Style
  • Themes
  • Behaviors
Forms
  • Button
  • ButtonGroup
  • Checkbox
  • ColorPicker
  • Combobox
  • Field
  • FileUpload
  • Input
  • InputGroup
  • InputOTP
  • Label
  • NativeSelect
  • NumberInput
  • PasswordInput
  • RadioGroup
  • Select
  • Slider
  • Switch
  • TagsInput
  • Textarea
  • Toggle
  • ToggleGroup
Overlays
  • AlertDialog
  • Command
  • ContextMenu
  • Dialog
  • Drawer
  • DropdownMenu
  • HoverCard
  • Menubar
  • NavigationMenu
  • Popover
  • Sheet
  • Toast
  • Tooltip
Display
  • Accordion
  • Alert
  • AspectRatio
  • Avatar
  • Badge
  • Breadcrumb
  • Card
  • Collapsible
  • Empty
  • Item
  • Kbd
  • Pagination
  • Progress
  • Separator
  • Skeleton
  • Spinner
  • Table
  • Tabs
  • Tree
Layout
  • Carousel
  • Resizable
  • ScrollArea
  • Sidebar
Dates
  • Calendar
  • DatePicker
  • DateRangePicker
  • TimePicker
Data
  • AreaChart
  • BarChart
  • Chart
  • DataTable
  • Kanban
  • LineChart
  • PieChart
  • RadarChart
  • RadialChart
  • VirtualList
Chat
  • Attachment
  • Message
  • MessageList
  • PromptInput
Elements UI / Chat / Attachment

Attachment

A file or source as a thumbnail, chip or row, with preview, size, upload progress and remove.

Grid

Thumbnails for a sent message. Hover or tab to a tile to reveal its remove button.

mountains.svg mountains.svg
q3-revenue.svg q3-revenue.svg
contract-final.pdf
standup.mp3
walkthrough.mp4
notes
removed: none
Code
<Attachments variant="grid">
  <Attachment e:for={f of state.files} e:key={(f) => f.id}
              data={f} onRemoveItem={(f) => removeFile(state, f)} />
</Attachments>

Usage

import { Attachments, Attachment, AttachmentEmpty, createAttachment, revokeAttachment } from "@elements/ui/attachment";

<Attachments variant="inline">
  <Attachment e:for={f of state.files} e:key={(f) => f.id}
              data={f} hoverCard
              onRemoveItem={(f) => removeFile(state, f)} />
</Attachments>

Examples

Inline

Chips for a prompt input. hoverCard shows a large preview on hover or keyboard focus.

mountains.svg mountains.svg image/svg+xml
q3-revenue.svg q3-revenue.svg image/svg+xml
contract-final.pdf application/pdf
standup.mp3 audio/mpeg
Code
<Attachments variant="inline" label="Files to send">
  <Attachment e:for={f of state.files} e:key={(f) => f.id}
              data={f} hoverCard showMediaType
              onRemoveItem={(f) => removeFile(state, f)} />
</Attachments>

List

Rows with media type and size. href opens the file.

mountains.svg mountains.svg image/svg+xml · 47 KB
q3-revenue.svg q3-revenue.svg image/svg+xml · 13 KB
contract-final.pdf application/pdf · 2.4 MB
standup.mp3 audio/mpeg · 6.1 MB
Code
<Attachments variant="list">
  <Attachment e:for={f of files} e:key={(f) => f.id}
              data={f} showMediaType showSize href={f.url ?? ""} />
</Attachments>

Uploading and errors

progress below 100 shows a bar; error marks the item. Neither changes its size.

dataset.csv 8.2 MB · 40%
mountains.svg mountains.svg 47 KB · 75%
dataset.csv 40%
mountains.svg mountains.svg 75%
dataset.csv 40%
mountains.svg mountains.svg 75%
Code
// progress 0..100 shows the bar; error marks it failed.
{ id: "u1", filename: "dataset.csv", mediaType: "text/csv", size: 8_600_000, progress: 40 }

<Attachments variant="list">
  <Attachment e:for={f of state.uploads} e:key={(f) => f.id} data={f} showSize />
</Attachments>

Sources

Source documents from the AI SDK show the globe and their title.

Elements manual: templates
pricing.md
Source
Elements manual: templates text/html
pricing.md text/markdown
Source text/plain
Code
<Attachments variant="inline" label="Sources">
  <Attachment data={{ id: "s1", type: "source-document", title: "Elements manual", sourceId: "man" }} />
</Attachments>

Custom icon and actions

icon replaces the category icon; the default slot adds actions; removeIcon swaps the remove icon. A broken image falls back to its type icon.

summary.txt 2.0 KB
missing.png missing.png
Code
<Attachment data={file} icon="sparkles">
  <Button variant="ghost" size="sm" icon label="Download"><Icon name="download" /></Button>
</Attachment>

<!-- removeIcon swaps the remove button's icon; a broken image falls back to the type icon. -->
<Attachment data={file} removeIcon="trash" onRemoveItem={(f) => remove(f)} />

Hover delays and a link

openDelay and closeDelay hold the hover card back; hoverAlign centers it. With href and onRemoveItem, remove sits above the link and never opens it.

q3-revenue.svg q3-revenue.svg
Code
<Attachment data={file} href={file.url}
            hoverCard openDelay={400} closeDelay={300} hoverAlign="center"
            onRemoveItem={(f) => remove(f)} />

Default layout

Attachments without a variant lays out as a grid of square tiles.

mountains.svg mountains.svg
notes.pdf
Code
<!-- variant defaults to grid. -->
<Attachments>
  <Attachment e:for={f of files} e:key={(f) => f.id} data={f} />
</Attachments>

Empty

AttachmentEmpty stands in when there is nothing to show.

No attachments
Drop files here
Nothing uploaded yet
Code
<Attachments e:if={state.files.length > 0}>...</Attachments>
<AttachmentEmpty e:else />
<AttachmentEmpty>Drop files here</AttachmentEmpty>

End alignment and classes

hoverAlign end lines the hover card up with the chip's end edge. class is appended to the Attachments, Attachment and AttachmentEmpty roots.

q4-forecast.svg q4-forecast.svg
brief.pdf
No attachments
Code
<!-- hoverAlign="end" lines the card's end edge up with the chip. -->
<Attachment data={file} hoverCard hoverAlign="end" />

<!-- class is appended to each root. -->
<Attachments class="my-strip">
  <Attachment data={file} class="my-chip" />
</Attachments>
<AttachmentEmpty class="my-strip" />
Reference Attachment in the manual Every part, attribute, slot, key and data attribute.
Prev VirtualListNext Message
Product
Manual Pricing Compare
Company
History Contact
Legal
Privacy Policy Acceptable Use Terms License Agreement
© Elements Dev Corporation 2026