File upload · dropzone
Drag-and-drop, paste or browse; files are checked for type, size and count, images get thumbnails, and each upload has its own progress, cancel and retry — as a dropzone, a compact bar, or a round avatar.
Drop, paste or browse · checked · uploaded one by one, each can be cancelled or retried
one fails on purpose, one isn't allowed
Attachments0 / 6
Click to upload or drag and drop
IMAGE, PDF, XLSX, DOCX · up to 5.0 MB · max 6 files · or paste with ⌘V
Compact · upload when you say so
Choose files or drag them herePDF, DOCX, TXT · up to 10 MB
Avatar · a ring shows the progress
Profile pictureSquare works best · PNG or JPG up to 2 MB
Usage
import { signal } from "./index.js";import { FileUpload } from "./components/upload.js"; const files = signal([]); // entries: { file, name, size, preview, status(), progress(), error(), result }FileUpload({ value: files, accept: "image/*,.pdf", maxSize: 5e6, maxFiles: 6, upload: (file, { onProgress, signal }) => { // any transport — here XHR for upload progress return new Promise((ok, fail) => { const x = new XMLHttpRequest(); x.open("POST", "/upload"); x.upload.onprogress = (e) => onProgress(e.loaded / e.total); x.onload = () => (x.status < 300 ? ok(JSON.parse(x.response)) : fail(new Error(x.statusText))); x.onerror = () => fail(new Error("Network error")); signal.addEventListener("abort", () => x.abort()); const fd = new FormData(); fd.append("file", file); x.send(fd); }); } })FileUpload({ variant: "compact", autoUpload: false, upload }) // an "Upload n files" buttonFileUpload({ variant: "avatar", accept: "image/*", upload }) // round, with a progress ring