# V spinner 12

> File Upload Progress

A shadcn/ui block from the [@cnippet](https://ui.cnippet.dev/) registry, listed on [shadcn.exchange](https://shadcn.exchange/r/cnippet/v-spinner-12).

- Page, with a live preview: https://shadcn.exchange/r/cnippet/v-spinner-12
- Screenshot: https://abzjhwgwpdpz7ua5.public.blob.vercel-storage.com/shots/cnippet/v-spinner-12-light-cfa2d7b387b56da9.png
- Registry item: https://ui.cnippet.dev/r/v-spinner-12.json
- Categories: spinner
- Listed: 2026-10-13, source last changed 2026-10-13

## Install

```bash
npx shadcn@latest add https://ui.cnippet.dev/r/v-spinner-12.json
```

Run it in a project that has shadcn/ui set up. It adds the files below and installs what they depend on.

## Dependencies

- Registry items: `@cnippet/spinner`

## Files

### `registry/default/variants/v-spinner-12.tsx`

```tsx
"use client";

import { UploadCloudIcon } from "lucide-react";
import { useState } from "react";
import { Button } from "@/registry/default/ui/button";
import { Spinner } from "@/registry/default/ui/spinner";

type Status = "idle" | "uploading" | "done";

export default function Particle() {
  const [status, setStatus] = useState<Status>("idle");

  function handleUpload() {
    setStatus("uploading");
    setTimeout(() => setStatus("done"), 2500);
  }

  return (
    <div className="w-full max-w-sm space-y-4 rounded-xl border p-5">
      <div className="flex items-center gap-3">
        <div className="flex size-10 items-center justify-center rounded-lg bg-muted">
          {status === "uploading" ? (
            <Spinner className="size-5 text-primary" />
          ) : (
            <UploadCloudIcon
              aria-hidden="true"
              className={`size-5 ${status === "done" ? "text-green-500" : "text-muted-foreground"}`}
            />
          )}
        </div>
        <div className="flex-1">
          <p className="font-medium text-sm">
            {status === "idle" && "Ready to upload"}
            {status === "uploading" && "Uploading report.pdf…"}
            {status === "done" && "Upload complete"}
          </p>
          <p className="text-muted-foreground text-xs">
            {status === "idle" && "Max file size 25 MB"}
            {status === "uploading" && "Please wait"}
            {status === "done" && "report.pdf · 4.2 MB"}
          </p>
        </div>
      </div>
      <Button
        className="w-full"
        disabled={status === "uploading" || status === "done"}
        onClick={handleUpload}
        variant={status === "done" ? "outline" : "default"}
      >
        {status === "uploading" && (
          <Spinner
            aria-hidden="true"
            className="size-4"
            data-icon="inline-start"
          />
        )}
        {status === "idle" && "Upload File"}
        {status === "uploading" && "Uploading…"}
        {status === "done" && "Uploaded"}
      </Button>
    </div>
  );
}
```
