About
A file drop zone that lights up when files are dragged over it, sinks and says 'let go to attach' while hovered, shakes to refuse files it won't accept, and also opens a picker on click so dragging is never the only way to attach files.
Built with React and Tailwind. Copy the prompt and paste it into Claude Code, Cursor or Lovable: your agent adds Drop Zone to your project and fits it to your theme.
Code
How Drop Zone is used: the demo's code. The component's own source comes with a free account.
Usage.tsx
"use client";
import * as React from "react";
import DropZone, { type DropRefusal } from "@/components/ui/drop-zone";
import { Attachment, formatBytes } from "@unlocalhosted/metalui";
import { DocumentIcon } from "@unlocalhosted/metalui/icons";
const MAX = 10_000_000;
const WHY: Record<DropRefusal["reason"], string> = {
type: "not a PDF or an image",
size: `larger than ${formatBytes(MAX)}`,
count: "one at a time",
};
export default function DropZoneDemo() {
const [files, setFiles] = React.useState<File[]>([]);
const [refused, setRefused] = React.useState<DropRefusal[]>([]);
return (
<div
role="region"
aria-label="Region files"
className="grid w-full max-w-[400px] gap-12"
>
<DropZone
icon={<DocumentIcon size={20} />}
accept="application/pdf,image/*"
maxSize={MAX}
description={`PDFs and images, up to ${formatBytes(MAX)}`}
onFiles={(took, no) => {
setFiles((all) => [...all, ...took]);
setRefused(no);
}}
/>
{refused.length > 0 && (
<p role="alert" className="m-0 type-meta text-form-field-error-ink">
{refused.map((r) => `${r.file.name} is ${WHY[r.reason]}`).join("; ")}.
</p>
)}
{files.map((f, i) => (
<Attachment
key={`${f.name}-${i}`}
name={f.name}
size={f.size}
onRemove={() => setFiles((all) => all.filter((x) => x !== f))}
/>
))}
</div>
);
}








