feat(ui): add MicroSteps expand/collapse to WipTaskList; exclude subtasks from WIP count
This commit is contained in:
@@ -1,13 +1,16 @@
|
|||||||
<script>
|
<script>
|
||||||
import { tasks, addTask, completeTask, uncompleteTask, deleteTask } from '$lib/stores/page.svelte.js';
|
import { tasks, addTask, completeTask, uncompleteTask, deleteTask } from '$lib/stores/page.svelte.js';
|
||||||
import { ChevronDown } from 'lucide-svelte';
|
import MicroSteps from '$lib/components/MicroSteps.svelte';
|
||||||
|
import { ChevronDown, ChevronRight } from 'lucide-svelte';
|
||||||
|
|
||||||
let { wipLimit = 3 } = $props();
|
let { wipLimit = 3 } = $props();
|
||||||
|
|
||||||
let newTaskText = $state('');
|
let newTaskText = $state('');
|
||||||
let showOverflow = $state(false);
|
let showOverflow = $state(false);
|
||||||
|
let expandedTaskIds = $state(new Set());
|
||||||
|
|
||||||
let activeTasks = $derived(tasks.filter(t => !t.done));
|
// Exclude subtasks from WIP count — only top-level tasks count
|
||||||
|
let activeTasks = $derived(tasks.filter(t => !t.done && !t.parentTaskId));
|
||||||
let visibleTasks = $derived(activeTasks.slice(0, wipLimit));
|
let visibleTasks = $derived(activeTasks.slice(0, wipLimit));
|
||||||
let overflowTasks = $derived(activeTasks.slice(wipLimit));
|
let overflowTasks = $derived(activeTasks.slice(wipLimit));
|
||||||
let hasOverflow = $derived(overflowTasks.length > 0);
|
let hasOverflow = $derived(overflowTasks.length > 0);
|
||||||
@@ -22,6 +25,16 @@
|
|||||||
function handleKeydown(e) {
|
function handleKeydown(e) {
|
||||||
if (e.key === 'Enter') handleAdd();
|
if (e.key === 'Enter') handleAdd();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toggleExpand(taskId) {
|
||||||
|
const next = new Set(expandedTaskIds);
|
||||||
|
if (next.has(taskId)) {
|
||||||
|
next.delete(taskId);
|
||||||
|
} else {
|
||||||
|
next.add(taskId);
|
||||||
|
}
|
||||||
|
expandedTaskIds = next;
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex flex-col gap-3">
|
<div class="flex flex-col gap-3">
|
||||||
@@ -44,23 +57,42 @@
|
|||||||
{:else}
|
{:else}
|
||||||
<div class="flex flex-col gap-1">
|
<div class="flex flex-col gap-1">
|
||||||
{#each visibleTasks as task (task.id)}
|
{#each visibleTasks as task (task.id)}
|
||||||
<div class="flex items-center gap-2 px-3 py-2 rounded-lg hover:bg-hover group"
|
<div>
|
||||||
style="transition-duration: var(--duration-ui)">
|
<!-- Task row -->
|
||||||
<button
|
<div class="flex items-center gap-2 px-3 py-2 rounded-lg hover:bg-hover group"
|
||||||
class="w-4 h-4 rounded border border-border-subtle flex items-center justify-center flex-shrink-0
|
style="transition-duration: var(--duration-ui)">
|
||||||
hover:border-accent"
|
<button
|
||||||
onclick={() => completeTask(task.id)}
|
class="w-4 h-4 rounded border border-border-subtle flex items-center justify-center flex-shrink-0
|
||||||
aria-label="Complete task"
|
hover:border-accent"
|
||||||
>
|
onclick={() => completeTask(task.id)}
|
||||||
</button>
|
aria-label="Complete task"
|
||||||
<span class="text-[13px] text-text flex-1 min-w-0 truncate">{task.text}</span>
|
></button>
|
||||||
<button
|
<span class="text-[13px] text-text flex-1 min-w-0 truncate">{task.text}</span>
|
||||||
class="text-text-tertiary hover:text-danger opacity-0 group-hover:opacity-100 text-[11px]"
|
<!-- Expand/collapse micro-steps toggle -->
|
||||||
onclick={() => deleteTask(task.id)}
|
<button
|
||||||
aria-label="Delete task"
|
class="opacity-0 group-hover:opacity-100 text-text-tertiary hover:text-accent"
|
||||||
>
|
onclick={() => toggleExpand(task.id)}
|
||||||
×
|
aria-label={expandedTaskIds.has(task.id) ? 'Collapse steps' : 'Expand steps'}
|
||||||
</button>
|
style="transition: opacity var(--duration-ui)"
|
||||||
|
>
|
||||||
|
{#if expandedTaskIds.has(task.id)}
|
||||||
|
<ChevronDown size={12} aria-hidden="true" />
|
||||||
|
{:else}
|
||||||
|
<ChevronRight size={12} aria-hidden="true" />
|
||||||
|
{/if}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="text-text-tertiary hover:text-danger opacity-0 group-hover:opacity-100 text-[11px]"
|
||||||
|
onclick={() => deleteTask(task.id)}
|
||||||
|
aria-label="Delete task"
|
||||||
|
>
|
||||||
|
×
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<!-- Micro-steps panel (expanded) -->
|
||||||
|
{#if expandedTaskIds.has(task.id)}
|
||||||
|
<MicroSteps parentTaskId={task.id} />
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user