file-uploader.tsx


Overview

file-uploader.tsx is a React client-side component file that implements a versatile and user-friendly file uploader UI. It supports drag-and-drop file selection, file preview (especially for images), file removal, upload progress visualization, and customizable file acceptance criteria (such as file types, max file size, and max file count). The component integrates with external upload handlers and provides user feedback through toast notifications.

Key features include:

This component is suitable for use in web applications that require users to upload files with real-time feedback and validation.


Detailed API Documentation

Utility Type Guard

isFileWithPreview(file: File): file is File & { preview: string }

Type guard that checks if a given File object has a preview property of type string. This is used internally to distinguish files with a generated preview URL (typically images).


Components

FilePreview

interface FilePreviewProps {
  file: File & { preview: string };
}
function FilePreview({ file }: FilePreviewProps): JSX.Element

Description:
Renders a thumbnail preview of the file if it is an image (file.type starts with "image/"). For non-image files, it renders a generic file icon.

Parameters:

Returns: JSX element showing either an image thumbnail or a file icon.

Usage Example:

<FilePreview file={fileWithPreview} />

FileCard

interface FileCardProps {
  file: File;
  onRemove: () => void;
  progress?: number;
}
function FileCard({ file, progress, onRemove }: FileCardProps): JSX.Element

Description:
Displays a card UI for a single file in the upload list. Shows file name, size, optional upload progress bar, and a remove button.

Parameters:

Returns: JSX element representing the file card UI.

Usage Example:

<FileCard
  file={file}
  progress={uploadProgress[file.name]}
  onRemove={() => handleRemoveFile(index)}
/>

FileUploader

interface FileUploaderProps extends React.HTMLAttributes<HTMLDivElement> {
  value?: File[];
  onValueChange?: (files: File[]) => void;
  onUpload?: (files: File[]) => Promise<void>;
  progresses?: Record<string, number>;
  accept?: DropzoneProps['accept'];
  maxSize?: DropzoneProps['maxSize'];
  maxFileCount?: DropzoneProps['maxFiles'];
  multiple?: boolean;
  disabled?: boolean;
  description?: string;
}
function FileUploader(props: FileUploaderProps): JSX.Element

Description:
Main file uploader component that provides drag-and-drop file selection, file list display with previews, upload progress, and file removal. It handles validation against file count and size, accepts customizable file types, and integrates with external upload logic.

Props:

Prop

Type

Default

Description

Example

value

File[]

undefined

Controlled value representing the current files selected/uploaded.

value={files}

onValueChange

(files: File[]) => void

undefined

Callback fired when the selected files change.

onValueChange={(files) => setFiles(files)}

onUpload

(files: File[]) => Promise<void>

undefined

Async callback triggered when files are dropped/added, to handle upload logic externally.

onUpload={uploadFiles}

progresses

Record<string, number>

undefined

Object mapping file names to their upload progress percentages (0-100).

progresses={{ "image.png": 50 }}

accept

DropzoneProps['accept']

{ "image/*": [] }

Accepted MIME types or file extensions for upload.

accept={{ "image/png": [], "image/jpeg": [] }}

maxSize

number

1024 * 1024 * 10000000 (large)

Maximum file size allowed in bytes.

maxSize={2 * 1024 * 1024} (2MB)

maxFileCount

number

100000000000 (very large)

Maximum number of files allowed to upload.

maxFileCount={4}

multiple

boolean

false

Enable multiple file selection.

multiple

disabled

boolean

false

Disable the uploader UI.

disabled

description

string

undefined

Custom description text shown below the dropzone area.

"Upload your documents here."

Returns: JSX element representing the whole file uploader UI.


Usage Example

import { FileUploader } from './file-uploader';

function MyUploadComponent() {
  const [files, setFiles] = React.useState<File[]>([]);
  const [progresses, setProgresses] = React.useState<Record<string, number>>({});

  async function handleUpload(filesToUpload: File[]) {
    // Example upload logic that updates progress
    for (const file of filesToUpload) {
      // Simulate upload with progress updates
      for (let progress = 0; progress <= 100; progress += 10) {
        setProgresses((prev) => ({ ...prev, [file.name]: progress }));
        await new Promise((r) => setTimeout(r, 100));
      }
    }
  }

  return (
    <FileUploader
      value={files}
      onValueChange={setFiles}
      onUpload={handleUpload}
      progresses={progresses}
      accept={{ 'image/*': [] }}
      maxSize={5 * 1024 * 1024} // 5MB max size
      maxFileCount={3}
      multiple
      description="Drag & drop up to 3 images or click to select."
    />
  );
}

Implementation Details and Algorithms


Interaction with Other Parts of the System


Visual Diagram

componentDiagram
    component FileUploader {
        +value?: File[]
        +onValueChange?: (files: File[]) => void
        +onUpload?: (files: File[]) => Promise<void>
        +progresses?: Record<string, number>
        +accept?: DropzoneProps['accept']
        +maxSize?: number
        +maxFileCount?: number
        +multiple?: boolean
        +disabled?: boolean
        +description?: string
    }
    component Dropzone
    component FileCard {
        +file: File
        +progress?: number
        +onRemove: () => void
    }
    component FilePreview {
      +file: File & { preview: string }
    }

    FileUploader --> Dropzone : renders
    FileUploader --> FileCard : renders for each file
    FileCard --> FilePreview : renders if image

Summary

file-uploader.tsx is a robust React component designed for intuitive file uploading with drag-and-drop support, previews, progress tracking, and user notifications. It is highly configurable and designed to integrate seamlessly with various upload backends and UI themes, making it a valuable asset in modern web applications requiring file input functionality.