Skip to content

Commit 0b1ace1

Browse files
committed
feat: add drag/drop and paste support for attachments
1 parent 08f9e69 commit 0b1ace1

1 file changed

Lines changed: 48 additions & 1 deletion

File tree

app/components/Chat.tsx

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ export default function Chat({ user }: { user: User }) {
7676
const creatingRef = useRef(false);
7777
const fileInputRef = useRef<HTMLInputElement | null>(null);
7878
const [attachments, setAttachments] = useState<Attachment[]>([]);
79+
const [isDraggingOver, setIsDraggingOver] = useState(false);
7980
const bucketName = process.env.NEXT_PUBLIC_SUPABASE_BUCKET_NAME || "";
8081

8182
const globalConversations = conversations.filter((c) => c.type === "global");
@@ -388,6 +389,45 @@ export default function Chat({ user }: { user: User }) {
388389
setAttachments((prev) => [...prev, ...files]);
389390
};
390391

392+
const handleDrop = (e: React.DragEvent<HTMLDivElement>) => {
393+
e.preventDefault();
394+
setIsDraggingOver(false);
395+
396+
const files = Array.from(e.dataTransfer.files || []);
397+
if (!files.length) return;
398+
399+
setAttachments((prev) => [...prev, ...files]);
400+
};
401+
402+
const handleDragOver = (e: React.DragEvent<HTMLDivElement>) => {
403+
e.preventDefault();
404+
setIsDraggingOver(true);
405+
};
406+
407+
const onDragLeave = (e: React.DragEvent<HTMLDivElement>) => {
408+
setIsDraggingOver(false);
409+
};
410+
411+
const handlePaste = (e: React.ClipboardEvent<HTMLDivElement>) => {
412+
const items = e.clipboardData.items;
413+
if (!items) return;
414+
415+
const files: File[] = [];
416+
417+
for (let i = 0; i < items.length; i++) {
418+
const item = items[i];
419+
420+
if (item.kind === "file") {
421+
const file = item.getAsFile();
422+
if (file) files.push(file);
423+
}
424+
}
425+
426+
if (files.length) {
427+
setAttachments((prev) => [...prev, ...files]);
428+
}
429+
};
430+
391431
const removeAttachment = (index: number) => {
392432
setAttachments((prev) => prev.filter((_, i) => i !== index));
393433
};
@@ -596,7 +636,14 @@ export default function Chat({ user }: { user: User }) {
596636
</div>
597637
)}
598638

599-
<div className="rounded-2xl border border-white/10 bg-neutral-900/35/80 backdrop-blur-sm flex items-center gap-1 px-2 py-0.5 pr-0.5 shadow-[0_6px_18px_rgba(0,0,0,0.22)] overflow-hidden">
639+
<div
640+
onPaste={handlePaste}
641+
tabIndex={0}
642+
onDrop={handleDrop}
643+
onDragOver={handleDragOver}
644+
onDragLeave={onDragLeave}
645+
className={`${isDraggingOver ? "border-white/50" : "border-white/10"} transition-all rounded-2xl border bg-neutral-900/35/80 backdrop-blur-sm flex items-center gap-1 px-2 py-0.5 pr-0.5 shadow-[0_6px_18px_rgba(0,0,0,0.22)] overflow-hidden`}
646+
>
600647
<input
601648
type="file"
602649
ref={fileInputRef}

0 commit comments

Comments
 (0)