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";
2
3import { 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';
8
9interface FileItem {
10 id: string;
11 name: string;
12 size: string;
13 progress: number;
14 type: 'image' | 'document';
15}
16
17export 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 ]);
24
25 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 };
34
35 const handleDrop = (e: React.DragEvent) => {
36 e.preventDefault();
37 e.stopPropagation();
38 setDragActive(false);
39 };
40
41 const removeFile = (id: string) => {
42 setFiles(prev => prev.filter(f => f.id !== id));
43 };
44
45 return (
46 <Card className="w-full max-w-xl mx-auto">
47 <CardContent className="p-6 space-y-4">
48 <div
49 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 10MB
62 </p>
63 </div>
64
65 <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 <Button
90 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}

Related Forms & Input Components

Command Palette

Search for a command to run...