Inputs
FileUpload
A drag-and-drop file upload queue with per-file progress, client-side validation, and a remove action — the upload mechanism itself is entirely up to you.
FileUploadPreview
Drag and drop files here, or click to browseAccepted: image/*,.pdfMax size: 5.0 MB
Usage
tsx
import { FileUpload } from "@vesture/react";
import type { UploadFile } from "@vesture/react";
function Example() {
const [files, setFiles] = useState<UploadFile[]>([]);
const handleFilesAdded = (added: File[]) => {
const entries: UploadFile[] = added.map((file) => ({
id: crypto.randomUUID(),
file,
status: "uploading",
progress: 0,
}));
setFiles((prev) => [...prev, ...entries]);
// Kick off your own upload per entry, then update its status/progress
// in files as it proceeds — FileUpload never does this part for you.
};
return (
<FileUpload
files={files}
onFilesAdded={handleFilesAdded}
onRemove={(id) => setFiles((prev) => prev.filter((f) => f.id !== id))}
maxSize={5 * 1024 * 1024}
accept="image/*,.pdf"
/>
);
}Behavior
- FileUpload is a controlled queue UI only — it has no upload logic or network code of any kind. onFilesAdded hands you the raw File[] the moment they're dropped or picked; you own assigning ids, performing the actual upload however your backend works, and pushing status/progress updates back into the files prop as it proceeds.
- Files exceeding maxSize, or that would push the queue past maxFiles, are rejected client-side before onFilesAdded ever fires — a synthesized status: "error" row appears in the queue with a message like "File exceeds 10MB limit", so a rejection is visible rather than silently dropped.
- Each row reuses Progress for its bar: indeterminate while status is "pending", determinate while "uploading"/"success", replaced by the error message (no bar) when "error".
- The dropzone is keyboard-focusable and Enter/Space-activatable to open the native file picker — drag-and-drop has no keyboard equivalent, so the picker is the accessible path and works without a mouse.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
| files | UploadFile[] | — | Required. The controlled list — { id, file, status, progress, error? } per row. You own this state entirely. |
| onFilesAdded | (files: File[]) => void | — | Fires with newly added, already-validated files — before any upload logic runs. |
| onRemove | (id: string) => void | — | Fires when a row's remove button is clicked, regardless of status; you decide whether to cancel an in-flight upload. |
| accept | string | — | Native file input accept attribute, e.g. "image/*,.pdf". |
| multiple | boolean | true | Allows selecting/dropping more than one file at a time. |
| maxSize | number | — | Bytes. Files over this size are rejected client-side with a synthesized error row. |
| maxFiles | number | — | Rejects files that would push files.length past this total. |
| disabled | boolean | — | Disables the dropzone and file picker. |