Logo

Voxlet UI

Download Button

A dynamic button with real-time download status and progress tracking.

Installation

  1. 1

    Install Shadcn Components

    npx shadcn@latest add button
  2. 2

    lib/utils.ts

    import { clsx, type ClassValue } from "clsx"
    import { twMerge } from "tailwind-merge"
        
    export function cn(...inputs: ClassValue[]) {
      return twMerge(clsx(inputs))
    }
  3. 3

    Copy the source code

    @/components/ui/download-button.tsx
    "use client"
    
    import { Download, Loader2, CheckCircle } from "lucide-react"
    import { Button } from "@/components/ui/button"
    import { cn } from "@/lib/utils"
    
    interface DownloadButtonProps {
        downloadStatus: "idle" | "downloading" | "downloaded" | "complete"
        progress: number
        onClick: () => void
        className?: string
    }
    
    export default function DownloadButton({ downloadStatus, progress, onClick, className }: DownloadButtonProps) {
        return (
            <Button
                onClick={onClick}
                className={cn(
                    "rounded-xl w-40 relative overflow-hidden select-none",
                    downloadStatus === "downloading" && "bg-primary/50 hover:bg-primary/50",
                    downloadStatus !== "idle" && "pointer-events-none",
                    className,
                )}
            >
                {downloadStatus === "idle" && (
                    <>
                        <Download className="h-4 w-4" />
                        Download
                    </>
                )}
                {downloadStatus === "downloading" && (
                    <div className="z-[5] flex items-center justify-center">
                        <Loader2 className="mr-2 h-4 w-4 animate-spin" />
                        {progress}%
                    </div>
                )}
                {downloadStatus === "downloaded" && (
                    <>
                        <CheckCircle className="h-4 w-4" />
                        <span className="t">Downloaded</span>
                    </>
                )}
                {downloadStatus === "complete" && <span className="text-primary">Download</span>}
                {downloadStatus === "downloading" && (
                    <div
                        className="absolute bottom-0 z-[3] h-full left-0 bg-primary inset-0 transition-all duration-200 ease-in-out"
                        style={{ width: `${progress}%` }}
                    />
                )}
            </Button>
        )
    }
    
    

Props

PropTypeDefaultDescription
classNamestringundefinedOptional custom class names for styling.
downloadStatus"idle" | "downloading" | "downloaded" | "complete""idle"Represents the current state of the download process.
progressnumber0Indicates the download progress percentage (0-100).
onClick() => voidundefinedCallback function triggered when the button is clicked.
Brought to you by Voxlet