Attachment
A file attachment card for AI chat messages. Renders a file or image inside a message with a type-aware preview, human-readable size, an upload-state machine (idle, uploading, success, error) with a progress bar, and slots for remove, retry, and custom actions.
Pro Features
Unlock advanced capabilities with the Pro version
Upload State Machine
A single uploadState prop moves the card between idle, uploading, success, and error — each with its own spinner, check, or alert
Type-Aware Previews
Image attachments render a real thumbnail from src, while PDFs, code, and documents fall back to a matching icon
Progress Feedback
The progress prop drives an accessible progressbar with a clamped 0–100 value and a live percentage while uploading
Human-Readable Sizes
Pass raw bytes and the exported formatBytes helper renders locale-safe units (KB, MB, GB) with no manual math
Remove, Retry & Actions
Built-in remove and retry controls plus a free-form actions slot for download or any custom per-file button
Token-Based Surfaces
Card, muted, and semantic status colors are all design tokens, so light and dark mode work with zero extra styling
Installation
Install via CLI
npx @moontra/moonui-cli add attachmentUsage
Examples
File Attachments in a Message
Compose Attachment cards inside a MessageContent column so files read as part of the conversation. Image types with a src render a thumbnail, while other types fall back to a type-aware icon (PDF, code, document). The size prop is formatted into a human-readable string with formatBytes.
Upload States
The uploadState prop drives a small state machine. uploading shows a spinner, a percentage, and a progress bar (progressbar role); success shows a check; error shows an alert plus a Retry action. Here the error card's onRetry actually flips it to success.
Actions and Removable
Build a pre-send attachment tray. The actions slot holds custom controls such as a download button, and onRemove renders an accessible Remove button that here actually removes the file from the list. When the tray empties it falls back to a placeholder.