From c96447981faae98eabe486ae5e515e998ea5564b Mon Sep 17 00:00:00 2001 From: Till JS Date: Tue, 24 Mar 2026 19:43:30 +0100 Subject: [PATCH] fix(todo): improve drag-and-drop handles and fix reorder persistence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replace hamburger icon with standard 6-dot grip icon for drag handles - Increase drag handle icon size (1rem → 1.25rem) and hit area - Fix reorder bug: handleDndFinalize was not calling reorderTasks(), so reordered items were never persisted and would revert on refresh - Add optimistic update with rollback on error in reorderTasks store Co-Authored-By: Claude Opus 4.6 (1M context) --- .../web/src/lib/components/TaskItem.svelte | 19 +++++++++++++------ .../web/src/lib/components/TaskList.svelte | 4 ++++ .../apps/web/src/lib/stores/tasks.svelte.ts | 8 +++++--- 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/apps/todo/apps/web/src/lib/components/TaskItem.svelte b/apps/todo/apps/web/src/lib/components/TaskItem.svelte index 03988a10c..4198015aa 100644 --- a/apps/todo/apps/web/src/lib/components/TaskItem.svelte +++ b/apps/todo/apps/web/src/lib/components/TaskItem.svelte @@ -301,8 +301,13 @@ >
- - + + + + + + +
@@ -706,9 +711,11 @@ flex-shrink: 0; display: flex; align-items: center; - padding: 0.25rem; - margin-left: -0.125rem; + justify-content: center; + padding: 0.5rem 0.375rem; + margin-left: -0.25rem; border-radius: 0.25rem; + min-height: 2rem; } .task-item:hover .drag-handle { @@ -730,8 +737,8 @@ } .drag-icon { - width: 1rem; - height: 1rem; + width: 1.25rem; + height: 1.25rem; color: currentColor; } diff --git a/apps/todo/apps/web/src/lib/components/TaskList.svelte b/apps/todo/apps/web/src/lib/components/TaskList.svelte index 739c99e74..026d317c0 100644 --- a/apps/todo/apps/web/src/lib/components/TaskList.svelte +++ b/apps/todo/apps/web/src/lib/components/TaskList.svelte @@ -197,6 +197,10 @@ // Task moved FROM another section TO this section onTaskDrop(movedTaskId, dropTargetDate); } + } else if (wasInThisList) { + // Task reordered within this list - persist the new order + const taskIds = newItems.map((t) => t.id); + tasksStore.reorderTasks(taskIds); } // Update local state and sync lastTaskKey to prevent $effect from reverting diff --git a/apps/todo/apps/web/src/lib/stores/tasks.svelte.ts b/apps/todo/apps/web/src/lib/stores/tasks.svelte.ts index a2a9dcf0f..dc21a6675 100644 --- a/apps/todo/apps/web/src/lib/stores/tasks.svelte.ts +++ b/apps/todo/apps/web/src/lib/stores/tasks.svelte.ts @@ -452,17 +452,19 @@ export const tasksStore = { */ async reorderTasks(taskIds: string[]) { error = null; + const previousTasks = [...tasks]; try { - await tasksApi.reorderTasks(taskIds); - // Update local order + // Optimistic update - set new order values tasks = tasks.map((t) => { const newOrder = taskIds.indexOf(t.id); return newOrder !== -1 ? { ...t, order: newOrder } : t; }); + await tasksApi.reorderTasks(taskIds); } catch (e) { + // Rollback on error + tasks = previousTasks; error = e instanceof Error ? e.message : 'Failed to reorder tasks'; console.error('Failed to reorder tasks:', e); - throw e; } },