@aadarshg214/file-upload-ui
v1.0.0
Published
A config-driven, accessible file upload component library
Maintainers
Readme
@file-upload/ui
A config-driven, accessible file upload component library built with React, TypeScript, and Tailwind CSS. Features multiple variants, themes, and real-time configuration editing.
✨ Features
- 🎨 Config-Driven: Fully customizable via JSON configuration
- ♿ Accessible: Keyboard navigation, screen reader support, ARIA labels
- 📦 NPM Ready: Proper package structure with TypeScript support
- 🎯 Multiple Variants: Button, dropzone, preview, and compact layouts
- 🌈 Theme Support: Default, minimal, modern, and classic themes
- 📱 Responsive: Works perfectly on all devices
- 🔧 TypeScript: Full type safety throughout
- ⚡ Fast: Built with Vite for lightning-fast development
- 💾 LocalStorage: Files persist across page refreshes
- 🖼️ Image Previews: Beautiful image previews with status overlays
🚀 Quick Start
Installation
npm install @file-upload/uiBasic Usage
import { FileUpload } from '@file-upload/ui'
function App() {
const handleFilesSelected = (files: File[]) => {
console.log('Files selected:', files)
}
return (
<FileUpload
onFilesSelected={handleFilesSelected}
config={{
variant: 'dropzone',
theme: 'modern',
maxSize: 10 * 1024 * 1024, // 10MB
acceptedTypes: ['image/*', '.pdf']
}}
/>
)
}📋 Component Variants
1. Button Variant
Simple button-style upload with icon placement options.
<FileUpload
config={{
variant: 'button',
size: 'md',
theme: 'default',
iconPlacement: 'left'
}}
/>2. Dropzone Variant
Drag-and-drop interface with visual feedback.
<FileUpload
config={{
variant: 'dropzone',
size: 'lg',
theme: 'modern',
borderStyle: 'dashed'
}}
/>3. Preview Variant
Upload with file previews and progress tracking.
<FileUpload
config={{
variant: 'preview',
showPreview: true,
showProgress: true,
acceptedTypes: ['image/*']
}}
onFileUpload={async (file) => {
// Handle file upload
await uploadToServer(file)
}}
/>4. Compact Variant
Minimal design for space-constrained layouts.
<FileUpload
config={{
variant: 'compact',
size: 'sm',
theme: 'minimal'
}}
/>🎨 Configuration System
The component is fully configurable via a JSON schema that's LLM-friendly with a simple, declarative structure:
interface FileUploadConfig {
// Variant configuration
variant: 'button' | 'dropzone' | 'preview' | 'compact'
size: 'sm' | 'md' | 'lg'
theme: 'default' | 'minimal' | 'modern' | 'classic'
// File restrictions
maxSize: number // in bytes
acceptedTypes: string[]
multiple: boolean
maxFiles?: number
// Styling
radius: 'none' | 'sm' | 'md' | 'lg' | 'full'
borderStyle: 'solid' | 'dashed' | 'dotted' | 'none'
iconPlacement: 'left' | 'right' | 'top' | 'bottom' | 'center'
// Labels and text
labels: {
title: string
subtitle: string
buttonText: string
dragText: string
dropText: string
errorText: string
successText: string
}
// Behavior
autoUpload: boolean
showProgress: boolean
showPreview: boolean
allowRemove: boolean
// Accessibility
ariaLabel: string
ariaDescribedBy?: string
}📝 JSON Configuration Examples
Basic Dropzone
{
"variant": "dropzone",
"size": "md",
"theme": "default",
"maxSize": 10485760,
"acceptedTypes": ["image/*", ".pdf", ".doc"],
"multiple": true,
"labels": {
"title": "Upload Files",
"subtitle": "Drag and drop files here or click to browse",
"buttonText": "Choose Files",
"dragText": "Drag files here",
"dropText": "Drop files here",
"errorText": "Error uploading file",
"successText": "File uploaded successfully"
}
}Image-Only Preview
{
"variant": "preview",
"size": "lg",
"theme": "modern",
"maxSize": 5242880,
"acceptedTypes": ["image/*"],
"multiple": true,
"showPreview": true,
"showProgress": true,
"autoUpload": true,
"labels": {
"title": "Upload Images",
"subtitle": "Drag and drop images here or click to browse",
"buttonText": "Select Images",
"dragText": "Drag images here",
"dropText": "Drop images here",
"errorText": "Error uploading image",
"successText": "Image uploaded successfully"
}
}Compact Button
{
"variant": "compact",
"size": "sm",
"theme": "minimal",
"maxSize": 2097152,
"acceptedTypes": [".pdf", ".doc", ".txt"],
"multiple": false,
"labels": {
"title": "Quick Upload",
"subtitle": "Select a document to upload",
"buttonText": "Choose File",
"dragText": "Drag file here",
"dropText": "Drop file here",
"errorText": "Error uploading file",
"successText": "File uploaded successfully"
}
}🛠️ API Reference
FileUpload Props
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| config | Partial<FileUploadConfig> | defaultConfig | Configuration object |
| onFilesSelected | (files: File[]) => void | - | Callback when files are selected |
| onFileUpload | (file: FileWithPreview) => Promise<void> | - | Callback for file upload |
| onFileRemove | (fileId: string) => void | - | Callback when file is removed |
| className | string | - | Additional CSS classes |
| disabled | boolean | false | Disable the component |
| storageKey | string | 'fileUpload' | localStorage key for persistence |
Utility Functions
import {
createFileUploadConfig,
getConfigFromJSON,
exportConfigToJSON,
validateConfig,
saveFilesToStorage,
loadFilesFromStorage,
clearFilesFromStorage
} from '@file-upload/ui'
// Create config with overrides
const config = createFileUploadConfig({
variant: 'button',
theme: 'modern'
})
// Parse JSON string to config
const config = getConfigFromJSON(jsonString)
// Export config to JSON
const jsonString = exportConfigToJSON(config)
// Validate config
const { isValid, errors } = validateConfig(config)
// Storage utilities
saveFilesToStorage(files, 'myUploadKey')
const files = loadFilesFromStorage('myUploadKey')
clearFilesFromStorage('myUploadKey')Preset Configurations
import { configPresets } from '@file-upload/ui'
// Use preset configurations
<FileUpload config={configPresets.imageOnly} />
<FileUpload config={configPresets.documentOnly} />
<FileUpload config={configPresets.compact} />
<FileUpload config={configPresets.modern} />🎯 Accessibility Features
- Keyboard Navigation: Full keyboard support with Enter/Space activation
- Screen Reader Support: Proper ARIA labels and descriptions
- Focus Management: Clear focus indicators and logical tab order
- Error Handling: Accessible error messages and validation feedback
- Drag & Drop: Keyboard fallback for drag-and-drop functionality
🎨 Theming
The component supports four built-in themes:
Default Theme
Clean, professional design with neutral colors.
Minimal Theme
Subtle borders and transparent backgrounds.
Modern Theme
Gradient buttons and blue accent colors.
Classic Theme
Traditional gray color scheme.
🧪 Demo
Run the development server to see the interactive demo:
npm run devVisit http://localhost:5173 to see:
- Live Demo: Interactive file upload with real-time configuration
- All Variants: Showcase of all component variants and themes
- Config Editor: Live JSON configuration editor with real-time preview
- Preset Configurations: Pre-built configurations for common use cases
Demo Features
Live Demo Tab
- Real-time component preview
- Current configuration display
- Upload summary with statistics
All Variants Tab
- Button variants (Default, Modern, Minimal)
- Dropzone variants (Modern, Classic)
- Preview variants (Image, Document)
- Compact variants (Small, Medium, Large)
Config Editor Tab
- Live JSON editor with syntax highlighting
- Real-time component preview
- Preset configuration buttons
- Copy/Reset functionality
📦 Building for Production
Build the Library
npm run build:libCreate NPM Package
npm run packDevelopment
npm run dev🔧 Development
Project Structure
src/
├── components/
│ ├── file-upload.tsx # Main component
│ ├── file-upload-button.tsx # Button variant
│ ├── file-upload-dropzone.tsx # Dropzone variant
│ └── file-upload-preview.tsx # Preview variant
├── types/
│ ├── config.ts # Configuration types
│ └── variants.ts # Variant types
├── config/
│ └── default-config.ts # Default configuration
├── utils/
│ ├── config.ts # Configuration utilities
│ └── storage.ts # Storage utilities
├── lib/
│ └── utils.ts # General utilities
└── demo/
└── App.tsx # Demo applicationAdding New Variants
- Add variant type to
types/variants.ts - Add styles to
variantStylesandthemeStyles - Implement variant logic in
file-upload.tsx - Create variant-specific component (optional)
- Update documentation
🛠 Tech Stack
- React 19 - Latest React with concurrent features
- TypeScript - Type safety and better developer experience
- Tailwind CSS - Utility-first CSS framework
- Vite - Fast build tool and dev server
- Radix UI - Accessible UI primitives
- clsx & tailwind-merge - Conditional styling utilities
🤝 Contributing
- Fork the repository
- Create a feature branch:
git checkout -b feature-name - Commit your changes:
git commit -am 'Add feature' - Push to the branch:
git push origin feature-name - Submit a pull request
📄 License
This project is licensed under the MIT License - see the LICENSE file for details.
🙏 Acknowledgments
- shadcn/ui for the component design patterns
- Radix UI for accessible primitives
- Tailwind CSS for the utility-first styling
- Vite for the fast build tool
