- Gallery
- Forms & Input
- File Upload Zone
New
File Upload Zone
A drag-and-drop file upload area with progress tracking.
Forms & Inputuploadfiledrag-dropprogressinput
Dependencies
Other dependencies:
@/components/ui/card@/components/ui/button@/components/ui/progress
How to use this component
Copy the code below into your project. Make sure you have the required shadcn/ui dependencies installed. Then import and use the component in your pages or layouts.
Code
1"use client";23import { useState } from 'react';4import { Card } from '@/components/ui/card';5import { Button } from '@/components/ui/button';6import { Progress } from '@/components/ui/progress';7import { UploadCloud, FileText, Image as ImageIcon, X, Check } from 'lucide-react';89interface FileItem {10 id: string;11 name: string;12 size: string;13 progress: number;14 type: 'image' | 'document';15}1617export default function FileUploadZone() {18 const [dragActive, setDragActive] = useState(false);19 const [files, setFiles] = useState<FileItem[]>([20 { id: '1', name: 'profile-photo.jpg', size: '2.4 MB', progress: 100, type: 'image' },21 { id: '2', name: 'document.pdf', size: '1.8 MB', progress: 65, type: 'document' },22 { id: '3', name: 'presentation.pptx', size: '5.2 MB', progress: 30, type: 'document' }23 ]);2425 const handleDrag = (e: React.DragEvent) => {26 e.preventDefault();27 e.stopPropagation();28 if (e.type === 'dragenter' || e.type === 'dragover') {29 setDragActive(true);30 } else if (e.type === 'dragleave') {31 setDragActive(false);32 }33 };3435 const handleDrop = (e: React.DragEvent) => {36 e.preventDefault();37 e.stopPropagation();38 setDragActive(false);39 };4041 const removeFile = (id: string) => {42 setFiles(prev => prev.filter(f => f.id !== id));43 };4445 return (46 <Card className="w-full max-w-xl mx-auto">47 <CardContent className="p-6 space-y-4">48 <div49 className={`border-2 border-dashed rounded-lg p-8 text-center transition-colors \` +50 `${dragActive ? 'border-primary bg-primary/5' : 'border-muted-foreground/25'}`}51 onDragEnter={handleDrag}52 onDragLeave={handleDrag}53 onDragOver={handleDrag}54 onDrop={handleDrop}55 >56 <UploadCloud className="w-12 h-12 mx-auto mb-4 text-muted-foreground" />57 <p className="text-lg font-medium mb-2">Drag & drop files here</p>58 <p className="text-sm text-muted-foreground mb-4">or</p>59 <Button variant="outline">Browse Files</Button>60 <p className="text-xs text-muted-foreground mt-4">61 PNG, JPG, PDF up to 10MB62 </p>63 </div>6465 <div className="space-y-3">66 {files.map(file => (67 <div key={file.id} className="flex items-center gap-3 p-3 bg-muted rounded-lg">68 <div className={`p-2 rounded \` +69 `${file.type === 'image' ? 'bg-blue-100 text-blue-600' : 'bg-orange-100 text-orange-600'}`}>70 {file.type === 'image' ? (71 <ImageIcon className="w-5 h-5" />72 ) : (73 <FileText className="w-5 h-5" />74 )}75 </div>76 <div className="flex-1 min-w-0">77 <div className="flex items-center justify-between mb-1">78 <p className="text-sm font-medium truncate">{file.name}</p>79 <span className="text-xs text-muted-foreground">{file.size}</span>80 </div>81 <Progress value={file.progress} className="h-1.5" />82 </div>83 <div className="flex items-center gap-2">84 {file.progress === 100 ? (85 <Check className="w-5 h-5 text-green-500" />86 ) : (87 <span className="text-xs text-muted-foreground">{file.progress}%</span>88 )}89 <Button90 variant="ghost"91 size="sm"92 className="h-6 w-6 p-0"93 onClick={() => removeFile(file.id)}94 >95 <X className="w-4 h-4" />96 </Button>97 </div>98 </div>99 ))}100 </div>101 </CardContent>102 </Card>103 );104}