Skip to content

christopherldo/upload-widget-web

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

19 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿ“ค React Upload Widget

React TypeScript TailwindCSS Vite License

A high-performance, minimizable, and feature-rich file upload widget built with React 19, Tailwind CSS 4, and Zustand.


๐Ÿ“– About The Project

This project is a modern, production-ready Upload Widget designed to handle file uploads with a polished user experience. It solves the common problem of managing complex file upload states (progress, error, cancellation) in web applications while maintaining a clean and unobtrusive UI.

The widget supports drag-and-drop, real-time progress tracking, and automatic image compression, all wrapped in a collapsible interface that stays out of the user's way.

โœจ Key Features

  • ๐Ÿš€ Drag & Drop Interface: Seamless file selection using react-dropzone.
  • ๐Ÿ“‰ Automatic Image Compression: Client-side image compression to save bandwidth and storage using HTML Canvas.
  • ๐Ÿ“Š Real-time Progress: Visual feedback for upload progress, total size, and compressed size.
  • ๐Ÿ”„ Robust State Management: Powered by Zustand and Immer for handling complex asynchronous flows.
  • ๐ŸŽจ Smooth Animations: Fluid transitions for collapsing/expanding and list updates using Motion.
  • โฏ๏ธ Control: Ability to cancel and retry individual uploads.
  • ๐Ÿงฉ Minimizable UI: A collapsible "floating" widget that expands only when needed.

๐Ÿ—๏ธ Architecture

sequenceDiagram
    participant User
    participant Widget as UI Component
    participant Store as Zustand Store
    participant Utils as Compressor
    participant API as Backend API

    User->>Widget: Drops File(s)
    Widget->>Store: addUploads(files)
    Store->>Store: Create Upload ID & Set Status 'progress'
    Store->>Utils: compressImage(file)
    Utils-->>Store: Compressed File
    Store->>API: POST /uploads (multipart/form-data)
    loop Upload Progress
        API-->>Store: onUploadProgress
        Store-->>Widget: Update Progress Bar
    end
    alt Success
        API-->>Store: 200 OK (URL)
        Store-->>Widget: Show Success State
    else Error
        API-->>Store: Error
        Store-->>Widget: Show Error / Retry Option
    end
Loading

๐Ÿ› ๏ธ Tech Stack

Core

Styling & UI

State & Data


๐Ÿš€ Getting Started

Follow these steps to get a local copy running.

Prerequisites

  • Node.js (v18+ recommended)
  • npm, yarn, or pnpm
  • Backend Server: The widget expects a backend running at http://localhost:3333/uploads to handle the POST requests.

Installation

  1. Clone the repository

    git clone https://github.com/yourusername/upload-widget.git
    cd upload-widget/web
  2. Install dependencies

    npm install
    # or
    pnpm install
    # or
    yarn install
  3. Start the development server

    npm run dev
  4. Open in browser Navigate to http://localhost:5173 to see the widget in action.


๐Ÿ’ป Usage

Development Commands

Command Description
npm run dev Starts the local development server with Vite.
npm run build Builds the project for production (TypeScript compile + Vite build).
npm run lint Runs ESLint to check for code quality issues.
npm run preview Previews the production build locally.

API Integration Example

The widget sends a POST request to the configured endpoint. Here is the expected structure:

Request:

  • Method: POST
  • URL: http://localhost:3333/uploads
  • Header: Content-Type: multipart/form-data
  • Body: file: (Binary)

Response (Expected by Widget):

{
  "url": "https://storage.example.com/uploads/image-123.png"
}

๐Ÿ“‚ Project Structure

web/
โ”œโ”€โ”€ src/
โ”‚   โ”œโ”€โ”€ components/
โ”‚   โ”‚   โ”œโ”€โ”€ ui/               # Generic UI components (Button, Progress Bar)
โ”‚   โ”‚   โ”œโ”€โ”€ upload-widget*.tsx # Core widget components (Header, List, Dropzone)
โ”‚   โ”‚   โ””โ”€โ”€ ...
โ”‚   โ”œโ”€โ”€ http/                 # API integration logic
โ”‚   โ”‚   โ””โ”€โ”€ upload-file-to-store.ts
โ”‚   โ”œโ”€โ”€ store/                # Global state (Zustand)
โ”‚   โ”‚   โ””โ”€โ”€ uploads.ts
โ”‚   โ”œโ”€โ”€ utils/                # Helper functions (Compression, Formatting)
โ”‚   โ”œโ”€โ”€ app.tsx               # Main application entry point
โ”‚   โ””โ”€โ”€ main.tsx              # React DOM rendering
โ”œโ”€โ”€ public/
โ”œโ”€โ”€ package.json
โ”œโ”€โ”€ tailwind.config.js
โ”œโ”€โ”€ tsconfig.json
โ””โ”€โ”€ vite.config.ts

๐Ÿ”ฎ Roadmap & Improvements

Based on the current implementation, here are suggested improvements:

  1. Environment Variables: Extract the hardcoded API URL (http://localhost:3333) into a .env file (e.g., VITE_API_URL) to support different environments.
  2. Upload Queue Limit: Implement a concurrency limit to prevent freezing the browser when uploading hundreds of files simultaneously.
  3. File Type Validation: Add stricter validation props to the UploadWidget to restrict specific file types (e.g., "Images only" or "PDFs only") before they reach the state.

Made with โค๏ธ by ChristopherLDO

About

A high-performance, minimizable file upload widget built with React 19, Tailwind CSS 4, and Zustand. Features drag-and-drop, real-time progress, and client-side image compression.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors