Drop Zone

DnD & Interaction

File or element drop target area.

Preview

Drop files here

or click to browse

Usage

example.jsx
import { DropZone } from "@/components/ui/drop-zone";

export default function Example() {
  return <DropZone />;
}

Source Code

Copy this file into components/ui/drop-zone.jsx in your project.

drop-zone.jsx
"use client";

import { forwardRef, useState } from "react";
import { cn } from "@/lib/utils";

const DropZone = forwardRef(({ className, onDrop: onDropProp, children, accept, ...props }, ref) => {
  const [over, setOver] = useState(false);

  const handleDrop = (e) => {
    e.preventDefault();
    setOver(false);
    const files = Array.from(e.dataTransfer.files);
    onDropProp?.(files);
  };

  return (
    <div ref={ref}
      onDragOver={(e) => { e.preventDefault(); setOver(true); }}
      onDragLeave={() => setOver(false)}
      onDrop={handleDrop}
      className={cn("flex min-h-[120px] items-center justify-center rounded-lg border-2 border-dashed p-6 text-center transition-colors",
        over ? "border-primary bg-primary/5" : "border-muted-foreground/25",
        className
      )}
      {...props}
    >
      {children || (
        <div className="text-sm text-muted-foreground">
          <p className="font-medium">Drop files here</p>
          <p className="mt-1 text-xs">or click to browse</p>
        </div>
      )}
    </div>
  );
});
DropZone.displayName = "DropZone";

export { DropZone };

Quick Install

Make sure you have the cn() utility set up. It requires clsx and tailwind-merge.

npm install clsx tailwind-merge