Components/Surfaces/Attachment
COMPONENT33.33

Attachment

File chips with preview or icon, name, meta line and remove action. States ride data-state; removal is one line of author JS.


INSTALL

1pnpm dlx @sayagodev/mo add attachment

Or import the files from the package (no copy):

1import "@sayagodev/mo/css/attachment.css";

EXAMPLES

Demo
Workspace
workspace.png PNG · 820 KB
Desk
desk-reference.jpg JPG · 1.1 MB
Office
office-reference.jpg JPG · 940 KB
sales-dashboard.pdf Uploading · 64%
message-renderer.tsx TypeScript · 12 KB
Group
briefing-notes.pdf PDF · 1.4 MB
workspace.png PNG · 820 KB
customers.csv CSV · 18 KB
renderer.tsx TSX · 12 KB
Image
Workspace
workspace.png PNG · 820 KB
Desk
desk-reference.jpg JPG · 1.1 MB
Office
office-reference.jpg JPG · 940 KB
Sizes
Default attachment PDF · 2.4 MB
Small attachment PDF · 2.4 MB
Extra small attachment
States
selected-file.pdf Ready to upload
design-system.zip Uploading · 64%
market-research.pdf Processing document
financial-model.xlsx Upload failed. Try again.
uploaded-report.pdf Uploaded · 1.8 MB
Trigger
label[data-attachment-trigger] wraps a hidden file input; removal from the list is one line of author JS (chip.remove()).

USAGE

1<div data-attachment-group>2  <div data-attachment>3    <div data-attachment-media><svg/></div>4    <div data-attachment-content>5      <span data-attachment-title>report.pdf</span>6      <small data-attachment-description>PDF · 2.4 MB</small>7    </div>8    <div data-attachment-actions>9      <button type="button" data-attachment-remove class="icon ghost xs" aria-label="Remove"></button>10    </div>11  </div>12</div>13 14<label data-attachment-trigger>Attach files<input type="file" multiple /></label>

API

NAMEKINDDESCRIPTION
[data-attachment]attributeChip row: bordered bg-card, hover tint when it holds controls
data-stateattributeidle (dashed) · uploading/processing (spinner) · error · done
aria-invalid="true"attributeAlias for data-state="error"
[data-attachment-media]attribute40px slot; data-variant="image" renders cover thumb
[data-attachment-title] / [data-attachment-description]attributeTruncating name + muted meta line
label[data-attachment-trigger]elementFile-picker label styled like button.outline
--mo-attachment-radius / -radius-xstokenChip and compact chip corner radius
--mo-attachment-media-size / -size-sm / -size-xstokenMedia slot footprint (40px default)
--mo-attachment-gap / -group-gaptokenChip padding and inter-chip spacing
--mo-attachment-width-vertical / -vertical-contenttokenVertical tile width and inner content width

FILES

src/css/attachment.css
Install:mo add attachment

THEMING · PLAYGROUND

This is the exact component from the examples above, wearing a completely different theme. Edit the tokens and --mo-* hooks in the editor — autocomplete knows them all — and the preview obeys in real time. Your CSS always wins.

Tokens & hooks — edit live
Global tokens
--accent--background--border--card--card-foreground--destructive--foreground--input--muted--muted-foreground--radius--ring
Component hooks
--mo-attachment-gap--mo-attachment-group-gap--mo-attachment-media-radius--mo-attachment-media-size--mo-attachment-media-size-sm--mo-attachment-media-size-xs--mo-attachment-radius--mo-attachment-radius-xs--mo-attachment-width-vertical--mo-attachment-width-vertical-content--mo-button-font-size--mo-button-height--mo-button-padding-x--mo-button-radius

Preview

Scan
scan-0412.pdf
2.1 MB · just now

Your CSS

Try it: type --mo- for the component hooks, or edit any value — the preview obeys in real time.