File upload component with drag-and-drop, type filtering, size and count limits, supporting single and multiple modes.
Images or PDF up to 5 MB
Add up to 5 workspace files
Compact feedback for files already added
product-roadmap.pdf
customer-import.csv
brand-video.mov
Inset surface
Clear border
Quiet upload
"use client";
import { useState } from "react";
import {
FileUpload,
type FileUploadFile,
} from "@/components/matos-ui/file-upload";
function createDemoFile(
name: string,
size: number,
type: string,
status: FileUploadFile["status"],
progress?: number,
error?: string,
): FileUploadFile {
return {
id: name,
file: new File([new Uint8Array(size)], name, {
type,
lastModified: Date.now(),
}),
status,
progress,
error,
};
}
export function FileUploadDemo() {
const [singleFiles, setSingleFiles] = useState<FileUploadFile[]>([]);
const [multiFiles, setMultiFiles] = useState<FileUploadFile[]>([]);
const [reviewFiles, setReviewFiles] = useState<FileUploadFile[]>(() => [
createDemoFile(
"product-roadmap.pdf",
420_000,
"application/pdf",
"success",
),
createDemoFile("customer-import.csv", 180_000, "text/csv", "uploading", 58),
createDemoFile(
"brand-video.mov",
9_800_000,
"video/quicktime",
"error",
undefined,
"Larger than 5 MB",
),
]);
return (
<div className="mx-auto grid w-full max-w-3xl gap-4">
<section className="grid gap-3 md:grid-cols-[1fr_1.1fr]">
<FileUpload
files={singleFiles}
onFilesChange={setSingleFiles}
accept="image/*,.pdf"
maxSize={5 * 1024 * 1024}
title="Upload asset"
description="Images or PDF up to 5 MB"
/>
<FileUpload
variant="outline"
multiple
maxFiles={5}
files={multiFiles}
onFilesChange={setMultiFiles}
title="Attach files"
description="Add up to 5 workspace files"
/>
</section>
<FileUpload
multiple
maxFiles={4}
maxSize={5 * 1024 * 1024}
files={reviewFiles}
onFilesChange={setReviewFiles}
state="uploading"
title="Review queue"
description="Compact feedback for files already added"
accept=".pdf,.csv,.png"
/>
<section className="grid grid-cols-1 gap-3 md:grid-cols-3">
<FileUpload
size="sm"
title="Default"
description="Inset surface"
accept=".pdf"
/>
<FileUpload
variant="outline"
size="sm"
title="Outline"
description="Clear border"
accept=".csv"
/>
<FileUpload
variant="ghost"
size="sm"
title="Ghost"
description="Quiet upload"
accept=".png"
/>
</section>
</div>
);
}
pnpm dlx shadcn@latest add https://matos-ui.com/r/file-upload.jsonimport { FileUpload } from '@/components/matos-ui/file-upload'<FileUpload
files={files}
onFilesChange={setFiles}
accept="image/*,.pdf"
maxSize={5 * 1024 * 1024}
/>| Prop | Type | Default |
|---|---|---|
files | FileUploadFile[] | — (uncontrolled if omitted) |
onFilesChange | (files: FileUploadFile[]) => void | — |
accept | string | — |
multiple | boolean | false |
maxSize | number | — |
maxFiles | number | — |
title | string | "Drag and drop your files" |
description | string | "or click to select a file" |
disabled | boolean | false |
size | "sm" | "md" | "lg" | "md" |
variant | "default" | "outline" | "ghost" | "default" |
export interface FileUploadFile {
file: File
id: string
error?: string
}FileUpload forwards standard props to <div role="button">. Internally it renders an <input type="file" className="sr-only" />.
Also exported: fileUploadVariants with slots root / icon / title / description / fileList / fileItem / fileName / fileSize / removeButton / errorText for easy customisation via tailwind-variants.
On This Page
Install Matos UI
Choose a package manager and copy one command for every component.