diff --git a/app/(app)/dashboard/header/ActionDropZones.tsx b/app/(app)/dashboard/header/ActionDropZones.tsx
deleted file mode 100644
index 5c09f60..0000000
--- a/app/(app)/dashboard/header/ActionDropZones.tsx
+++ /dev/null
@@ -1,170 +0,0 @@
-/**
- * @file app/(app)/dashboard/header/ActionDropZones.tsx
- * @description Client component rendering interactive drop zones for editing and deleting tasks during drag-and-drop operations.
- */
-
-"use client";
-
-import { useState, useEffect } from "react";
-import { useRouter } from "next/navigation";
-import { Pencil, Trash2, LucideIcon } from "lucide-react";
-
-/**
- * Properties for the ActionDropZones component.
- *
- * @interface ActionDropZonesProps
- * @property {(taskId: string) => void} onTaskDelete - Callback triggered when a task is dropped onto the delete zone.
- * @property {(isDragging: boolean) => void} onDragStateChange - Callback notified when global drag state begins or ends.
- */
-interface ActionDropZonesProps {
- onTaskDelete: (taskId: string) => void;
- onDragStateChange: (isDragging: boolean) => void;
-}
-
-/**
- * Configuration structure for individual drop zones (edit and delete).
- *
- * @interface ActionDropZoneConfig
- * @property {"edit" | "delete"} id - Unique identifier for the drop zone.
- * @property {string} label - Text description shown inside the drop zone.
- * @property {LucideIcon} icon - Icon component displayed next to the label.
- * @property {boolean} isOver - Flag indicating if a dragged element is currently hovering over the zone.
- * @property {(val: boolean) => void} setIsOver - State updater for the hover flag.
- * @property {(taskId: string) => void} onDropAction - Action executed when a task is dropped onto the zone.
- * @property {string} activeStyle - Tailwind styling applied when hovered.
- * @property {string} inactiveStyle - Tailwind styling applied when idle.
- */
-interface ActionDropZoneConfig {
- id: "edit" | "delete";
- label: string;
- icon: LucideIcon;
- isOver: boolean;
- setIsOver: (val: boolean) => void;
- onDropAction: (taskId: string) => void;
- activeStyle: string;
- inactiveStyle: string;
-}
-
-/**
- * Renders interactive drop targets for editing or deleting tasks when a drag action starts,
- * conditionally displaying the edit zone only for authorized creators.
- *
- * @param {ActionDropZonesProps} props - The component props.
- * @returns {JSX.Element | null} The rendered drop zones container or null if no drag is active.
- */
-export default function ActionDropZones({
- onTaskDelete,
- onDragStateChange,
-}: ActionDropZonesProps) {
- const router = useRouter();
- const [isDragging, setIsDragging] = useState(false);
- const [, setIsCreator] = useState(false);
- const [isEditOver, setIsEditOver] = useState(false);
- const [isDeleteOver, setIsDeleteOver] = useState(false);
-
- useEffect(() => {
- /**
- * Handles the global dragstart window event to activate drop zones if authorized.
- *
- * @param {DragEvent} e - The native drag event.
- */
- const handleDragStart = (e: DragEvent) => {
- const allowed = e.dataTransfer?.getData("isCreator") === "true";
- if (allowed) {
- setIsDragging(true);
- setIsCreator(allowed);
- onDragStateChange(true);
- }
- };
-
- /**
- * Handles the global dragend window event to reset drop zone states.
- */
- const handleDragEnd = () => {
- setIsDragging(false);
- setIsCreator(false);
- setIsEditOver(false);
- setIsDeleteOver(false);
- onDragStateChange(false);
- };
-
- window.addEventListener("dragstart", handleDragStart);
- window.addEventListener("dragend", handleDragEnd);
-
- return () => {
- window.removeEventListener("dragstart", handleDragStart);
- window.removeEventListener("dragend", handleDragEnd);
- };
- }, [onDragStateChange]);
-
- if (!isDragging) return null;
-
- const zones: ActionDropZoneConfig[] = [
- {
- id: "edit" as const,
- label: "Drop to Edit",
- icon: Pencil,
- isOver: isEditOver,
- setIsOver: setIsEditOver,
- onDropAction: (taskId: string) =>
- router.push(`/tasks?task=edit&id=${taskId}`),
- activeStyle:
- "bg-primary text-black border-primary scale-110 shadow-lg animate-pulse",
- inactiveStyle:
- "bg-primary/10 border-primary/40 text-primary scale-100 opacity-90 hover:opacity-100",
- },
- {
- id: "delete" as const,
- label: "Drop to Delete",
- icon: Trash2,
- isOver: isDeleteOver,
- setIsOver: setIsDeleteOver,
- onDropAction: onTaskDelete,
- activeStyle:
- "bg-destructive border-destructive scale-110 shadow-lg animate-pulse",
- inactiveStyle:
- "bg-destructive/10 border-destructive/40 text-destructive scale-100 opacity-90 hover:opacity-100",
- },
- ];
-
- return (
-
- {zones.map(
- ({
- id,
- label,
- icon: Icon,
- isOver,
- setIsOver,
- onDropAction,
- activeStyle,
- inactiveStyle,
- }) => (
-
{
- e.preventDefault();
- e.dataTransfer.dropEffect = "move";
- setIsOver(true);
- }}
- onDragLeave={() => setIsOver(false)}
- onDrop={(e) => {
- e.preventDefault();
- setIsOver(false);
- const taskId = e.dataTransfer.getData("text/plain");
- if (taskId) {
- onDropAction(taskId);
- }
- }}
- className={`flex items-center gap-2 px-4 py-2.5 rounded-xl font-medium text-sm border-2 border-dashed cursor-pointer select-none transition-all duration-300 ease-out transform ${
- isOver ? activeStyle : inactiveStyle
- }`}
- >
-
- {label}
-
- ),
- )}
-
- );
-}
diff --git a/app/(app)/dashboard/header/DropZoneButton.tsx b/app/(app)/dashboard/header/DropZoneButton.tsx
new file mode 100644
index 0000000..b897b46
--- /dev/null
+++ b/app/(app)/dashboard/header/DropZoneButton.tsx
@@ -0,0 +1,84 @@
+/**
+ * @file app/(app)/dashboard/header/DropZoneButton.tsx
+ * @description Client component rendering an interactive drop zone target button with dynamic visual feedback for drag-and-drop operations.
+ */
+
+"use client";
+
+import { LucideIcon } from "lucide-react";
+
+/**
+ * Properties for the DropZoneButton component.
+ *
+ * @interface DropZoneButtonProps
+ * @property {string} label - The text label displayed inside the drop zone.
+ * @property {LucideIcon} icon - The Lucide icon component to render alongside the label.
+ * @property {"primary" | "secondary" | "danger"} [variant="primary"] - Visual style variant of the button.
+ * @property {boolean} isOver - Indicates whether a dragged item is currently hovering over the drop zone.
+ * @property {(e: React.DragEvent) => void} onDragOver - Callback handler triggered when a drag element moves over the zone.
+ * @property {() => void} onDragLeave - Callback handler triggered when a drag element leaves the zone.
+ * @property {(e: React.DragEvent) => void} onDrop - Callback handler triggered when an item is dropped onto the zone.
+ */
+interface DropZoneButtonProps {
+ label: string;
+ icon: LucideIcon;
+ variant?: "primary" | "secondary" | "danger";
+ isOver: boolean;
+ onDragOver: (e: React.DragEvent) => void;
+ onDragLeave: () => void;
+ onDrop: (e: React.DragEvent) => void;
+}
+
+/**
+ * Renders a drop target button with dynamic hover state animations and variant-based color schemes for drag operations.
+ *
+ * @param {DropZoneButtonProps} props - The component props.
+ * @returns {JSX.Element} The rendered drop zone button component.
+ */
+export function DropZoneButton({
+ label,
+ icon: Icon,
+ variant = "primary",
+ isOver,
+ onDragOver,
+ onDragLeave,
+ onDrop,
+}: DropZoneButtonProps) {
+ const baseStyles =
+ "flex items-center gap-2 px-4 py-2.5 rounded-xl font-medium text-sm border-2 border-dashed cursor-pointer select-none transition-all duration-300 ease-out transform";
+
+ const activeStyles = "scale-110 shadow-lg animate-pulse";
+ const inactiveStyles = "scale-100 opacity-90 hover:opacity-100";
+
+ const variants = {
+ primary: {
+ active: "bg-primary text-black border-primary",
+ inactive: "bg-primary/10 border-primary/40 text-primary",
+ },
+ secondary: {
+ active: "bg-card text-foreground border-foreground",
+ inactive:
+ "bg-card/60 border-foreground-muted/50 text-foreground hover:border-foreground",
+ },
+ danger: {
+ active: "bg-destructive text-destructive-foreground border-destructive",
+ inactive: "bg-destructive/10 border-destructive/40 text-destructive",
+ },
+ };
+
+ const stateStyles = isOver
+ ? `${activeStyles} ${variants[variant].active}`
+ : `${inactiveStyles} ${variants[variant].inactive}`;
+
+ return (
+
+
+ {label}
+
+ );
+}
diff --git a/app/(app)/dashboard/header/DropZones.tsx b/app/(app)/dashboard/header/DropZones.tsx
new file mode 100644
index 0000000..f2a35e7
--- /dev/null
+++ b/app/(app)/dashboard/header/DropZones.tsx
@@ -0,0 +1,115 @@
+/**
+ * @file app/(app)/dashboard/header/DropZones.tsx
+ * @description Client component rendering interactive drop zones for editing and deleting tasks during drag-and-drop operations.
+ */
+
+"use client";
+
+import { useState, useEffect } from "react";
+import { useRouter } from "next/navigation";
+import { Pencil, Trash2 } from "lucide-react";
+import { DropZoneButton } from "./DropZoneButton";
+
+/**
+ * Properties for the DropZones component.
+ *
+ * @interface DropZonesProps
+ * @property {(taskId: string) => void} onTaskDelete - Callback function triggered when a task is dropped onto the delete zone.
+ * @property {(isDragging: boolean) => void} onDragStateChange - Callback function notifying parent components of global drag state changes.
+ */
+interface DropZonesProps {
+ onTaskDelete: (taskId: string) => void;
+ onDragStateChange: (isDragging: boolean) => void;
+}
+
+/**
+ * Renders drag-and-drop zones (Edit and Delete) that appear when a user initiates a task drag operation.
+ *
+ * @param {DropZonesProps} props - The component props.
+ * @returns {JSX.Element | null} The rendered drop zones container or null when no active drag operation is ongoing.
+ */
+export default function DropZones({
+ onTaskDelete,
+ onDragStateChange,
+}: DropZonesProps) {
+ const router = useRouter();
+ const [isDragging, setIsDragging] = useState(false);
+ const [activeZone, setActiveZone] = useState<"edit" | "delete" | null>(null);
+
+ useEffect(() => {
+ /**
+ * Handles global dragstart events to detect creator task dragging and reveal drop zones.
+ *
+ * @param {DragEvent} e - The native DOM drag event object.
+ */
+ const handleDragStart = (e: DragEvent) => {
+ const allowed = e.dataTransfer?.getData("isCreator") === "true";
+ if (allowed) {
+ setIsDragging(true);
+ onDragStateChange(true);
+ }
+ };
+
+ /**
+ * Handles global dragend events to reset active drop zones and state.
+ */
+ const handleDragEnd = () => {
+ setIsDragging(false);
+ setActiveZone(null);
+ onDragStateChange(false);
+ };
+
+ window.addEventListener("dragstart", handleDragStart);
+ window.addEventListener("dragend", handleDragEnd);
+ return () => {
+ window.removeEventListener("dragstart", handleDragStart);
+ window.removeEventListener("dragend", handleDragEnd);
+ };
+ }, [onDragStateChange]);
+
+ if (!isDragging) return null;
+
+ return (
+
+ {/* Edit Zone */}
+ {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = "move";
+ setActiveZone("edit");
+ }}
+ onDragLeave={() => setActiveZone(null)}
+ onDrop={(e) => {
+ e.preventDefault();
+ setActiveZone(null);
+ const taskId = e.dataTransfer.getData("text/plain");
+ if (taskId) router.push(`/tasks?task=edit&id=${taskId}`);
+ }}
+ />
+
+ {/* Delete Zone */}
+ {
+ e.preventDefault();
+ e.dataTransfer.dropEffect = "move";
+ setActiveZone("delete");
+ }}
+ onDragLeave={() => setActiveZone(null)}
+ onDrop={(e) => {
+ e.preventDefault();
+ setActiveZone(null);
+ const taskId = e.dataTransfer.getData("text/plain");
+ if (taskId) onTaskDelete(taskId);
+ }}
+ />
+
+ );
+}
diff --git a/app/(app)/dashboard/header/Header.tsx b/app/(app)/dashboard/header/Header.tsx
index 26545b6..3b5b812 100644
--- a/app/(app)/dashboard/header/Header.tsx
+++ b/app/(app)/dashboard/header/Header.tsx
@@ -8,7 +8,7 @@
import { Plus, Sparkles } from "lucide-react";
import TrashLink from "./TrashLink";
import { useState } from "react";
-import ActionDropZones from "./ActionDropZones";
+import DropZones from "./DropZones";
import { ActionButton } from "@/app/components/ui/buttons/ActionButton";
/**
@@ -40,7 +40,7 @@ export default function Header({