FileUpload
Select files by browsing or dropping them. Rayden validates file type, size, and count, then updates your controlled list. Your app owns the actual upload and its progress.
Import
import { FileUpload, type FileUploadFileData } from "@raydenui/ui";Basic selection
The demos keep selected files in this page. They do not send them to a server.
const [files, setFiles] = useState<FileUploadFileData[]>([]);
<FileUpload files={files} onFilesChange={setFiles} />;Accepted files enter the list with status: "pending". Selection and removal call onFilesChange. If you supply onUpload, it receives each accepted browser File and its corresponding list item after the list update; update that item’s status rather than adding it again.
Restrict file types and size
<FileUpload
files={files}
onFilesChange={setFiles}
accept=".pdf,.doc,.docx"
maxSize={10 * 1024 * 1024}
description="PDF, DOC up to 10MB"
/>Type, size, and count rejection messages appear next to the drop zone and are announced to assistive technology. onError optionally receives each message. The same checks apply to file browsing and drag-and-drop.
Multiple files
<FileUpload files={files} onFilesChange={setFiles} multiple maxFiles={5} />Images
Connect an upload
const [files, setFiles] = useState<FileUploadFileData[]>([]);
function updateFile(id: string, changes: Partial<FileUploadFileData>) {
setFiles((current) => current.map((item) => (item.id === id ? { ...item, ...changes } : item)));
}
<FileUpload
files={files}
onFilesChange={setFiles}
onUpload={async (file, item) => {
updateFile(item.id, { status: "uploading", progress: 0 });
try {
const body = new FormData();
body.append("file", file);
const response = await fetch("/api/upload", { method: "POST", body });
if (!response.ok) throw new Error("Upload failed. Please try again.");
updateFile(item.id, { status: "complete", progress: 100, uploadedAt: new Date() });
} catch (error) {
updateFile(item.id, {
status: "error",
error: error instanceof Error ? error.message : "Upload failed. Please try again.",
});
}
}}
/>;Implement /api/upload in your app. For incremental progress, update the item’s progress from your upload client’s progress callback. Keep your browser File objects or upload jobs keyed by the item ID if you implement retry or cancellation. Validate uploads again on the server.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
files | FileUploadFileData[] | Required | Controlled file list |
onFilesChange | (files: FileUploadFileData[]) => void | Required | Selection and removal updates |
onUpload | (file: File, item: FileUploadFileData) => void | — | Start an upload for an accepted item |
onError | (message: string) => void | — | File validation rejection |
onRemove | (id: string) => void | — | Cleanup/cancel a removed upload |
onRetry | (id: string) => void | — | Retry an errored upload |
onDownload | (id: string) => void | — | Download a completed item |
accept | string | — | Extensions, MIME types, or MIME wildcards |
maxSize | number | — | Maximum bytes per file |
multiple | boolean | false | Allow multiple files |
maxFiles | number | — | Maximum list length |
disabled | boolean | false | Disable browsing and dropping new files |
title | string | "Upload Documents" | Header title |
showHeader | boolean | false | Show header |
onClose | () => void | — | Header close action |
description | string | — | Guidance inside the drop zone |
className | string | — | Additional wrapper classes |
Accessibility
- Browse Files is a keyboard-operable button.
- Validation messages use an alert region.
- Upload progress and completion have live status announcements.
- Removal controls identify pending files by name.