fix(todo): scrollable sheet body + subtasks animate complete with parent

FokusLayout:
- Wrap DnD zone, footer, and completed-today in .sheet-body
- .sheet-body is the scroll container (flex:1, overflow-y:auto)
- .sheet-content no longer manages scroll — allows scrolling to
  the "Heute erledigt" section below the main task list

KanbanTaskCard:
- Inline subtasks all appear as done (checked + strikethrough) during
  the parent's completing animation via isAnimatingComplete flag
- Subtask clicks blocked during animation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-03-31 17:50:22 +02:00
parent 23aa5e26ab
commit 999c54a5a1
2 changed files with 59 additions and 47 deletions

View file

@ -142,39 +142,21 @@
onDelete={onColumnDelete ? () => onColumnDelete(i) : undefined}
/>
<div
class="sheet-content"
use:dndzone={{
items: tasks,
flipDurationMs: 200,
dropTargetStyle: {},
dropTargetClasses: ['fokus-drop-target'],
type: 'task-dnd',
}}
onconsider={(e) => handleDndConsider(column.id, e)}
onfinalize={(e) => handleDndFinalize(column.id, column, e)}
>
{#each tasks.filter((t) => t.id !== SHADOW_PLACEHOLDER_ITEM_ID) as task (task.id)}
<div class="task-card-wrapper">
<KanbanTaskCard
{task}
onToggleComplete={() => onTaskToggle(task)}
onSave={(data) => onTaskUpdate(task.id, data)}
onDelete={() => onTaskDelete(task.id)}
/>
</div>
{/each}
</div>
<div class="sheet-footer">
<QuickAddTaskInline onAdd={(title) => handleAddTask(column, title)} />
</div>
{#if completedToday.length > 0}
<div class="completed-today">
<div class="completed-today-label">Heute erledigt</div>
{#each completedToday as task (task.id)}
<div class="completed-today-item">
<div class="sheet-body">
<div
class="sheet-content"
use:dndzone={{
items: tasks,
flipDurationMs: 200,
dropTargetStyle: {},
dropTargetClasses: ['fokus-drop-target'],
type: 'task-dnd',
}}
onconsider={(e) => handleDndConsider(column.id, e)}
onfinalize={(e) => handleDndFinalize(column.id, column, e)}
>
{#each tasks.filter((t) => t.id !== SHADOW_PLACEHOLDER_ITEM_ID) as task (task.id)}
<div class="task-card-wrapper">
<KanbanTaskCard
{task}
onToggleComplete={() => onTaskToggle(task)}
@ -184,7 +166,27 @@
</div>
{/each}
</div>
{/if}
<div class="sheet-footer">
<QuickAddTaskInline onAdd={(title) => handleAddTask(column, title)} />
</div>
{#if completedToday.length > 0}
<div class="completed-today">
<div class="completed-today-label">Heute erledigt</div>
{#each completedToday as task (task.id)}
<div class="completed-today-item">
<KanbanTaskCard
{task}
onToggleComplete={() => onTaskToggle(task)}
onSave={(data) => onTaskUpdate(task.id, data)}
onDelete={() => onTaskDelete(task.id)}
/>
</div>
{/each}
</div>
{/if}
</div>
</div>
{/each}
@ -250,27 +252,37 @@
opacity: 0.75;
}
.sheet-content {
/* Scrollable wrapper for DnD zone + footer + completed section */
.sheet-body {
flex: 1;
overflow-y: auto;
padding: 0.75rem 1rem;
min-height: 120px;
display: flex;
flex-direction: column;
scrollbar-width: thin;
scrollbar-color: rgba(0, 0, 0, 0.08) transparent;
}
.sheet-content::-webkit-scrollbar {
:global(.dark) .sheet-body {
scrollbar-color: rgba(255, 255, 255, 0.1) transparent;
}
.sheet-body::-webkit-scrollbar {
width: 4px;
}
.sheet-content::-webkit-scrollbar-track {
.sheet-body::-webkit-scrollbar-track {
background: transparent;
}
.sheet-content::-webkit-scrollbar-thumb {
.sheet-body::-webkit-scrollbar-thumb {
background: rgba(0, 0, 0, 0.08);
border-radius: 2px;
}
:global(.dark) .sheet-content::-webkit-scrollbar-thumb {
:global(.dark) .sheet-body::-webkit-scrollbar-thumb {
background: rgba(255, 255, 255, 0.1);
}
.sheet-content {
padding: 0.75rem 1rem;
min-height: 120px;
}
.task-card-wrapper {
margin-bottom: 0.5rem;
}

View file

@ -291,21 +291,21 @@
{/if}
</div>
<!-- Inline subtasks -->
<!-- Inline subtasks — shown while incomplete; during animation all appear as done -->
{#if task.subtasks && task.subtasks.length > 0 && !task.isCompleted}
<!-- svelte-ignore a11y_no_static_element_interactions -->
<div class="subtasks-inline" onpointerdown={(e) => e.stopPropagation()}>
{#each task.subtasks as subtask (subtask.id)}
<button
class="subtask-row"
class:done={subtask.isCompleted}
class:done={subtask.isCompleted || isAnimatingComplete}
onclick={(e) => {
e.stopPropagation();
toggleSubtask(subtask.id);
if (!isAnimatingComplete) toggleSubtask(subtask.id);
}}
>
<span class="subtask-check" class:checked={subtask.isCompleted}>
{#if subtask.isCompleted}<Check size={10} />{/if}
<span class="subtask-check" class:checked={subtask.isCompleted || isAnimatingComplete}>
{#if subtask.isCompleted || isAnimatingComplete}<Check size={10} />{/if}
</span>
<span class="subtask-title">{subtask.title}</span>
</button>