Uplofile is open sourceStar on GitHub

Form Integration

Integrate uplofile into standard HTML forms with hidden input for form submission.

Preview

Code

1import {
2 UplofileRoot,
3 UplofileDropzone,
4 UplofileTrigger,
5 UplofilePreview,
6 UplofileHiddenInput,
7 type UploadFileItem,
8} from "@/components/ui/uplofile";
9import {
10 IoCloudUploadOutline,
11 IoSendOutline,
12 IoCheckmarkCircleOutline,
13 IoReloadOutline,
14 IoAttachOutline,
15 IoAlertCircleOutline,
16} from "react-icons/io5";
17import { mockUpload } from "@/lib/utils.ts";
18
19export default function FormIntegrationDemo() {
20 const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
21 e.preventDefault();
22 const formData = new FormData(e.currentTarget);
23 console.log("Form submitted:", Object.fromEntries(formData));
24 alert("Form submitted! Check console for data.");
25 };
26
27 return (
28 <form className="space-y-6 max-w-2xl mx-auto" onSubmit={handleSubmit}>
29 <div className="grid gap-2">
30 <label className="text-sm font-bold text-gray-700 uppercase tracking-tight">
31 Title
32 </label>
33 <input
34 type="text"
35 name="title"
36 className="flex h-10 w-full rounded-lg border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 shadow-sm"
37 placeholder="e.g. Project Proposal Q1"
38 required
39 />
40 </div>
41
42 <div className="grid gap-2">
43 <label className="text-sm font-bold text-gray-700 uppercase tracking-tight flex items-center gap-2">
44 <IoAttachOutline className="h-3 w-3" />
45 Attachments
46 </label>
47 <UplofileRoot upload={mockUpload} multiple name="attachments">
48 <UplofileHiddenInput />
49
50 <UplofileDropzone className="group relative border-2 border-dashed border-muted-foreground/20 rounded-xl p-8 text-center transition-all hover:border-primary/50 hover:bg-primary/5 data-[dragging=true]:border-primary data-[dragging=true]:bg-primary/10">
51 <UplofileTrigger>
52 <div className="flex flex-col items-center gap-3 cursor-pointer">
53 <div className="p-3 rounded-full bg-primary/10 text-primary group-hover:scale-110 transition-transform">
54 <IoCloudUploadOutline className="h-6 w-6" />
55 </div>
56 <div className="grid gap-0.5">
57 <span className="text-sm font-semibold text-gray-900">
58 Click to upload or drag and drop
59 </span>
60 <span className="text-xs text-muted-foreground">
61 PDF, PNG, JPG up to 10MB
62 </span>
63 </div>
64 </div>
65 </UplofileTrigger>
66 </UplofileDropzone>
67
68 <UplofilePreview
69 render={({ items }) => (
70 <div className="mt-4 space-y-2">
71 {items.map((item) => (
72 <FormFileItem key={item.uid} item={item} />
73 ))}
74 </div>
75 )}
76 />
77 </UplofileRoot>
78 </div>
79
80 <div className="pt-4 border-t">
81 <button
82 type="submit"
83 className="w-full inline-flex items-center justify-center gap-2 rounded-lg text-sm font-bold ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 bg-gray-900 text-white hover:bg-gray-800 h-11 px-8 shadow-lg active:scale-[0.98]"
84 >
85 <IoSendOutline className="h-4 w-4" />
86 Submit Application
87 </button>
88 </div>
89 </form>
90 );
91}
92
93function FormFileItem({ item }: { item: UploadFileItem }) {
94 return (
95 <div className="flex items-center justify-between p-3 rounded-lg border bg-white shadow-sm animate-in fade-in slide-in-from-top-1">
96 <div className="flex items-center gap-3 overflow-hidden">
97 <div
98 className={`p-1.5 rounded-md ${item.status === "error" ? "bg-destructive/10 text-destructive" : "bg-muted text-muted-foreground"}`}
99 >
100 {item.status === "error" ? (
101 <IoAlertCircleOutline className="h-3 w-3" />
102 ) : (
103<IoAttachOutline className="h-3 w-3" />
104 )}
105 </div>
106 <span
107 className={`text-xs font-medium truncate max-w-[200px] ${item.status === "error" ? "text-destructive" : ""}`}
108 >
109 {item.name}
110 </span>
111 </div>
112 <div className="flex items-center gap-2">
113 {item.status === "uploading" && (
114 <>
115 <span className="text-[10px] font-bold text-muted-foreground">
116 {item.progress}%
117 </span>
118 <IoReloadOutline className="h-3 w-3 animate-spin text-primary" />
119 </>
120 )}
121 {item.status === "done" && (
122 <IoCheckmarkCircleOutline className="h-4 w-4 text-emerald-500" />
123 )}
124 {item.status === "error" && (
125 <span className="text-[10px] font-bold text-destructive uppercase">
126 Failed
127 </span>
128 )}
129 </div>
130 </div>
131 );
132}

Key Points

  • Uses UplofileHiddenInput for form compatibility
  • Set name prop on Root for the form field name
  • Uploaded file URLs accessible as JSON in FormData
  • Works with standard form handling and validation