File Upload

PreviousNext

File upload component with drag-and-drop, type filtering, size and count limits, supporting single and multiple modes.

Upload assetimages, .pdf

Images or PDF up to 5 MB

Attach filesAny file

Add up to 5 workspace files

Review queue.pdf, .csv, .png

Compact feedback for files already added

  • product-roadmap.pdf

    410.2 KB
    Ready
  • customer-import.csv

    175.8 KB
    Uploading
  • brand-video.mov

    9.3 MBLarger than 5 MB
    Invalid
Default.pdf

Inset surface

Outline.csv

Clear border

Ghost.png

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>
  );
}

Installation

pnpm dlx shadcn@latest add https://matos-ui.com/r/file-upload.json

Usage

import { FileUpload } from '@/components/matos-ui/file-upload'
<FileUpload
  files={files}
  onFilesChange={setFiles}
  accept="image/*,.pdf"
  maxSize={5 * 1024 * 1024}
/>

Reference

Props

PropTypeDefault
filesFileUploadFile[]— (uncontrolled if omitted)
onFilesChange(files: FileUploadFile[]) => void—
acceptstring—
multiplebooleanfalse
maxSizenumber—
maxFilesnumber—
titlestring"Drag and drop your files"
descriptionstring"or click to select a file"
disabledbooleanfalse
size"sm" | "md" | "lg""md"
variant"default" | "outline" | "ghost""default"

Interfaces

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.