Upload Progress
LoadingFile upload progress with percentage display.
Preview
Done
67%
23%
Usage
example.jsx
import { UploadProgress } from "@/components/ui/upload-progress";
export default function Example() {
return <UploadProgress />;
}Source Code
Copy this file into components/ui/upload-progress.jsx in your project.
upload-progress.jsx
"use client";
import { forwardRef } from "react";
import { cn } from "@/lib/utils";
const UploadProgress = forwardRef(({ className, fileName, progress = 0, status = "uploading", onCancel, ...props }, ref) => (
<div ref={ref} className={cn("flex items-center gap-3 rounded-lg border p-3", className)} {...props}>
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-muted text-muted-foreground">
<svg className="h-5 w-5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M7 16a4 4 0 01-.88-7.903A5 5 0 1115.9 6L16 6a5 5 0 011 9.9M15 13l-3-3m0 0l-3 3m3-3v12" /></svg>
</div>
<div className="flex-1 min-w-0">
<div className="flex items-center justify-between text-sm">
<span className="truncate font-medium">{fileName}</span>
<span className="shrink-0 text-xs text-muted-foreground">
{status === "complete" ? "Done" : status === "error" ? "Error" : `${Math.round(progress)}%`}
</span>
</div>
<div className="mt-1.5 h-1.5 w-full overflow-hidden rounded-full bg-muted">
<div className={cn("h-full rounded-full transition-all",
status === "complete" ? "bg-green-500" : status === "error" ? "bg-red-500" : "bg-primary"
)} style={{ width: `${progress}%` }} />
</div>
</div>
{onCancel && status === "uploading" && (
<button onClick={onCancel} className="shrink-0 text-muted-foreground hover:text-foreground">
<svg className="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" /></svg>
</button>
)}
</div>
));
UploadProgress.displayName = "UploadProgress";
export { UploadProgress };
Quick Install
Make sure you have the cn() utility set up. It requires clsx and tailwind-merge.
npm install clsx tailwind-merge