File Upload
Advanced file upload component with drag & drop, progress tracking, validation, and preview support
Installation
Install the File Upload component using the nocta-ui CLI:
npx nocta-ui add file-upload
Then import the component:
import { FileUpload } from '@/components/ui/file-upload';
Basic Usage
Basic File Upload
Basic File Upload
Click to upload or drag and drop
Accepted types: image/*,.pdf,.doc,.docx
Max size: 5 MB
Max files: 5
Single File Upload
Single File Upload
Click to upload a document
Accepted types: .pdf,.doc,.docx
Max size: 10 MB
Image Upload with Preview
Image Upload with Preview
Click to upload images or drag and drop
Accepted types: image/*
Max size: 2 MB
Max files: 10
Sizes
Three size options are available: sm
, md
, and lg
. The default size is md
.
Small Size
Click to upload or drag and drop
Medium Size (Default)
Click to upload or drag and drop
Large Size
Click to upload or drag and drop
Component States
Disabled State
Disabled State
Upload is disabled
File Types & Validation
File Type Restrictions
// Images only
<FileUpload accept="image/*" />
// Specific image types
<FileUpload accept="image/jpeg,image/png,image/gif" />
// Documents
<FileUpload accept=".pdf,.doc,.docx,.txt" />
// Multiple types
<FileUpload accept="image/*,.pdf,.doc,.docx,text/*" />
// All files
<FileUpload accept="*/*" />
File Size Limits
// 1MB limit
<FileUpload maxSize={1024 * 1024} />
// 5MB limit
<FileUpload maxSize={5 * 1024 * 1024} />
// 50MB limit
<FileUpload maxSize={50 * 1024 * 1024} />
File Count Limits
// Single file only
<FileUpload multiple={false} />
// Up to 5 files
<FileUpload multiple maxFiles={5} />
// Up to 20 files
<FileUpload multiple maxFiles={20} />
// Unlimited files
<FileUpload multiple />
Custom Upload Implementation
Basic Upload Function
const handleUpload = async (filesToUpload: FileUploadFile[]) => {
for (const fileData of filesToUpload) {
const formData = new FormData();
formData.append('file', fileData.file);
try {
// Update status to uploading
setFiles(prevFiles =>
prevFiles.map(f =>
f.id === fileData.id
? { ...f, status: 'uploading', progress: 0 }
: f
)
);
// Make upload request
const response = await fetch('/api/upload', {
method: 'POST',
body: formData,
});
if (response.ok) {
// Success
setFiles(prevFiles =>
prevFiles.map(f =>
f.id === fileData.id
? { ...f, status: 'success', progress: 100 }
: f
)
);
} else {
throw new Error('Upload failed');
}
} catch (error) {
// Error
setFiles(prevFiles =>
prevFiles.map(f =>
f.id === fileData.id
? { ...f, status: 'error', error: 'Upload failed' }
: f
)
);
}
}
};
Upload with Progress Tracking
const handleUploadWithProgress = async (filesToUpload: FileUploadFile[]) => {
for (const fileData of filesToUpload) {
const formData = new FormData();
formData.append('file', fileData.file);
try {
setFiles(prevFiles =>
prevFiles.map(f =>
f.id === fileData.id
? { ...f, status: 'uploading', progress: 0 }
: f
)
);
await new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
// Track upload progress
xhr.upload.addEventListener('progress', (e) => {
if (e.lengthComputable) {
const progress = (e.loaded / e.total) * 100;
setFiles(prevFiles =>
prevFiles.map(f =>
f.id === fileData.id
? { ...f, progress }
: f
)
);
}
});
xhr.addEventListener('load', () => {
if (xhr.status === 200) {
setFiles(prevFiles =>
prevFiles.map(f =>
f.id === fileData.id
? { ...f, status: 'success', progress: 100 }
: f
)
);
resolve(xhr.response);
} else {
reject(new Error('Upload failed'));
}
});
xhr.addEventListener('error', () => {
reject(new Error('Upload failed'));
});
xhr.open('POST', '/api/upload');
xhr.send(formData);
});
} catch (error) {
setFiles(prevFiles =>
prevFiles.map(f =>
f.id === fileData.id
? { ...f, status: 'error', error: 'Upload failed' }
: f
)
);
}
}
};
Accessibility
The File Upload component includes comprehensive accessibility features:
- Keyboard Navigation: Full keyboard support with Enter and Space keys
- Screen Reader Support: Proper ARIA labels and announcements
- Focus Management: Visible focus indicators and logical tab order
- Progress Announcements: Screen readers announce upload progress
- Error Handling: Clear error messages for assistive technologies
API Reference
FileUpload Props
Prop | Type | Default | Description |
---|---|---|---|
variant | 'default' | 'default' | 'compact' | 'default' | Visual style variant |
size | 'sm' | 'md' | 'lg' | 'md' | Size of the upload area |
multiple | boolean | false | Allow multiple file selection |
accept | string | - | Accepted file types (MIME types or extensions) |
maxSize | number | - | Maximum file size in bytes |
maxFiles | number | - | Maximum number of files |
disabled | boolean | false | Disable the upload component |
files | FileUploadFile[] | [] | Array of files |
onFilesChange | (files: FileUploadFile[]) => void | - | Callback when files change |
onUpload | (files: FileUploadFile[]) => Promise<void> | - | Upload function |
showProgress | boolean | true | Show upload progress |
showPreview | boolean | true | Show image previews |
uploadText | string | 'Click to upload or drag and drop' | Upload zone text |
dragText | string | 'Drop files here' | Drag over text |
className | string | - | Additional CSS classes |