VisorVisor
ComponentsForm

File Upload

A drag-and-drop file upload zone with file validation, keyboard activation, and customizable content.

Default

Drag and drop files here, or click to browse

Accepted: image/* · Max 5MB

Multiple Files

Drag and drop files here, or click to browse

Accepted: image/*,.pdf · Max 10MB · Up to 5 files

Disabled

Drag and drop files here, or click to browse

All file types accepted · Max 10MB

Installation

npx visor add file-upload

This copies two files into your project:

  • components/ui/file-upload/file-upload.tsx — the component
  • components/ui/file-upload/file-upload.module.css — the styles

Usage

import { FileUpload } from '@/components/ui/file-upload/file-upload';

export default function Example() {
  return (
    <FileUpload
      accept="image/*"
      maxSize={5}
      maxFiles={3}
      onFilesChange={(files) => console.log(files)}
    />
  );
}

API Reference

PropTypeDefaultDescription
acceptstringAccepted file types (e.g., 'image/*', '.pdf,.doc').
maxSizenumber10Maximum file size in MB.
maxFilesnumber1Maximum number of files allowed.
disabledbooleanfalseDisables the drop zone.
onFilesChange(files: File[]) => voidCallback when valid files are selected or dropped.

The File Upload component is a drop zone only — it handles file selection and validation but does not manage file lists, progress tracking, or upload logic. Compose it with your own file list and upload implementation.

Accessibility

  • The drop zone renders as a <button> so it is reachable via Tab and activatable with Enter/Space
  • Keyboard users can open the native file picker via Enter or Space
  • aria-label defaults to "Upload files" — override it to describe the expected file type (e.g., "Upload profile photo")
  • Drag-over state is communicated visually via a border highlight; consider pairing with an aria-live region to announce when files are accepted or rejected
  • Screen readers announce validation errors (wrong file type, file too large) via an aria-live="polite" region