File Upload Demo
This demo shows a styled native file input with:
- Drag-and-drop support
- File type and size validation (JPG, JPEG, PNG, max 1MB)
- Simulated presigned URL request before upload
- Fake progress indicator that completes on "upload"
- Single file only (no multi-file)
- Error simulation controls
The core logic is written in vanilla TypeScript, with the UI connected via Vue. No actual files are uploaded anywhere.
Please upload an image.
Choose a file or drag and drop it here
Files can be JPG, JPEG or PNG & 1MB max
Recommended file size: 1000x1000 pixels
Error Simulation
Toggle these options before selecting a file to simulate error scenarios.
State Gallery
Below is a visual reference of all UI states and error scenarios covered by this component.
UI States
Initial state, no file selected. Save button is disabled.
Choose a file or drag and drop it here
Files can be JPG, JPEG or PNG & 1MB max
Recommended file size: 1000x1000 pixels
Choose FileAfter file selection, requesting presigned URL from server. Progress bar is empty.
Choose a file or drag and drop it here
Files can be JPG, JPEG or PNG & 1MB max
Recommended file size: 1000x1000 pixels
Choose FileFile is being uploaded. Progress bar shows upload progress.
Choose a file or drag and drop it here
Files can be JPG, JPEG or PNG & 1MB max
Recommended file size: 1000x1000 pixels
Choose FileUpload finished successfully. Progress bar is green. Save button is enabled.
Choose a file or drag and drop it here
Files can be JPG, JPEG or PNG & 1MB max
Recommended file size: 1000x1000 pixels
Choose FileError States
User selected a file with unsupported extension. No retry available.
Choose a file or drag and drop it here
Files can be JPG, JPEG or PNG & 1MB max
Recommended file size: 1000x1000 pixels
Choose FileUser selected a file exceeding the size limit. No retry available.
Choose a file or drag and drop it here
Files can be JPG, JPEG or PNG & 1MB max
Recommended file size: 1000x1000 pixels
Choose FileServer failed to provide upload URL. Retry button shown.
Choose a file or drag and drop it here
Files can be JPG, JPEG or PNG & 1MB max
Recommended file size: 1000x1000 pixels
Choose FileConnection lost during upload at 65% progress. Retry button shown.
Choose a file or drag and drop it here
Files can be JPG, JPEG or PNG & 1MB max
Recommended file size: 1000x1000 pixels
Choose FileAdditional Scenarios
These scenarios are not yet implemented or cannot be shown statically.
Allow user to retry failed upload without re-selecting file. Available for server errors (presigned URL failure, upload failure). Not available for validation errors.
Visual feedback when dragging file over dropzone. Implemented but not shown in gallery (requires interaction).
User clicks X button during active upload. Currently resets to idle with no specific feedback.
User loses network connection during upload. No offline detection or retry UI.
Server takes too long to respond. No timeout handling or feedback.
How it Works
- File Selection: Select a file via the button or drag-and-drop
- Validation: File type and size are validated client-side
- Presigned URL: A simulated delay represents fetching a presigned URL from the server
- Upload Progress: A fake progress bar animates to completion
- Complete: The Save button becomes enabled
Retry Logic
Server errors (presigned URL failures and upload failures) show a Retry button that allows the user to attempt the upload again without re-selecting the file. Validation errors (wrong file type, file too large) do not show a retry button since those require selecting a different file.
Architecture
The upload logic is split into pure TypeScript functions:
validateFile()- Validates file type and sizeformatFileSize()- Converts bytes to human-readable formatrequestPresignedUrl()- Simulates server request for upload URL (supports failure simulation)simulateUpload()- Runs fake progress animation (supports failure at configurable percentage)uploadFile()- Orchestrates the full flow with simulation options
This separation keeps the Vue component thin and makes the logic testable and reusable.