Add Droppable Areas
Next, we need to make the columns droppable targets. This tells @dnd-kit where tasks can be dropped.
Make Columns Droppable
Update src/components/column.tsx:
import { useDroppable } from "@dnd-kit/core";
import { Badge } from "@/components/ui/badge";
import TaskCard from "@/components/task-card";
import type { Doc } from "../../convex/_generated/dataModel";
type ColumnProps = {
title: string;
status: string;
tasks: Doc<"tasks">[];
};
function Column({ title, status, tasks }: ColumnProps) {
const { setNodeRef, isOver } = useDroppable({ id: status });
const borderColor: Record<string, string> = {
todo: "border-l-blue-500",
"in-progress": "border-l-amber-500",
done: "border-l-green-500",
};
return (
<div
ref={setNodeRef}
className={`rounded-lg border-l-4 bg-muted/50 p-4 transition-colors ${borderColor[status]} ${isOver ? "bg-muted" : ""}`}
>
<div className="mb-4 flex items-center justify-between">
<h2 className="text-sm font-semibold uppercase tracking-wide text-muted-foreground">
{title}
</h2>
<Badge variant="secondary">{tasks.length}</Badge>
</div>
<div className="space-y-3">
{tasks.length === 0 ? (
<p className="py-8 text-center text-sm text-muted-foreground">
No tasks
</p>
) : (
tasks.map((task) => <TaskCard key={task._id} task={task} />)
)}
</div>
</div>
);
}
export default Column;
Notice the new imports and the useDroppable hook at the top of the component. Here is what we added:
-
useDroppable({ id: status })registers this column as a drop target. Theidis the column’s status string (e.g.,"todo"), which is whathandleDragEndreceives asover.id. -
ref={setNodeRef}tells @dnd-kit which DOM element is the drop zone. -
isOveris a boolean that istruewhen a dragged item is hovering over this column. We use it to darken the background as a visual hint.
Checkpoint: Commit your progress.
git add .
git commit -m "kanban-12: Make columns droppable with useDroppable"
git push