fix: always separate completed checklist items from active list

Completed items now consistently appear below unchecked items in both
the editor and the note card preview. Replaces the flaky two-state
hide/show toggle with a simple expand/collapse for the done section.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Frederic Cabassut
2026-03-07 21:56:51 +01:00
co-authored by Claude Opus 4.6
parent 5ce8601a92
commit da57418de9
3 changed files with 35 additions and 42 deletions
+8 -17
View File
@@ -20,11 +20,10 @@
let { content, onChange }: Props = $props();
let items = $state<ChecklistItem[]>(parseChecklist(content));
let hideCompleted = $state(false);
let showDoneSection = $state(false);
let doneExpanded = $state(false);
const flipDurationMs = 150;
let activeItems = $derived(hideCompleted ? items.filter((i) => !i.checked) : items);
let activeItems = $derived(items.filter((i) => !i.checked));
let doneItems = $derived(items.filter((i) => i.checked));
let doneCount = $derived(doneItems.length);
@@ -103,11 +102,12 @@
}
function handleDndConsider(e: CustomEvent<DndEvent<ChecklistItem>>) {
items = e.detail.items;
// Merge reordered active items with done items
items = [...e.detail.items, ...items.filter((i) => i.checked)];
}
function handleDndFinalize(e: CustomEvent<DndEvent<ChecklistItem>>) {
items = e.detail.items;
items = [...e.detail.items, ...items.filter((i) => i.checked)];
emitChange();
}
</script>
@@ -164,24 +164,15 @@
{#if doneCount > 0}
<div class="mt-2 border-t border-[var(--border-subtle)] pt-2">
<button
onclick={() => {
if (!hideCompleted) {
hideCompleted = true;
showDoneSection = false;
} else {
showDoneSection = !showDoneSection;
}
}}
onclick={() => (doneExpanded = !doneExpanded)}
class="flex items-center gap-1 text-xs text-[var(--text-muted)] hover:text-[var(--text)]"
data-testid="checklist-toggle-done"
>
<ChevronRight class="h-3 w-3 transition-transform duration-150 {hideCompleted && showDoneSection ? 'rotate-90' : ''}" />
<ChevronRight class="h-3 w-3 transition-transform duration-150 {doneExpanded ? 'rotate-90' : ''}" />
{doneCount} done
</button>
{#if !hideCompleted}
<!-- Completed items are inline in the main list, toggle hides them -->
{:else if showDoneSection}
{#if doneExpanded}
<div class="mt-1 space-y-1 pl-5" data-testid="checklist-done-section">
{#each doneItems as item (item.id)}
<div class="flex items-center gap-2">
+13 -12
View File
@@ -40,6 +40,10 @@
: []
);
const activeChecklistItems = $derived(checklistItems.filter(i => !i.checked));
const doneChecklistItems = $derived(checklistItems.filter(i => i.checked));
const sortedChecklistItems = $derived([...activeChecklistItems, ...doneChecklistItems]);
function stop(fn: () => void) {
return (e: Event) => {
e.stopPropagation();
@@ -47,19 +51,16 @@
};
}
function toggleChecklistItem(index: number) {
function toggleChecklistItem(item: ChecklistItem) {
const lines = note.content.split('\n');
let checkIndex = 0;
for (let i = 0; i < lines.length; i++) {
const line = lines[i];
if (line.startsWith('- [x] ') || line.startsWith('- [ ] ')) {
if (checkIndex === index) {
lines[i] = line.startsWith('- [x] ')
? `- [ ] ${line.slice(6)}`
: `- [x] ${line.slice(6)}`;
break;
}
checkIndex++;
const text = line.replace(/^- \[[ x]\] /, '');
if (text === item.text && line.startsWith(item.checked ? '- [x] ' : '- [ ] ')) {
lines[i] = item.checked
? `- [ ] ${text}`
: `- [x] ${text}`;
break;
}
}
updateNote(note.id, { content: lines.join('\n') });
@@ -93,12 +94,12 @@
{#if note.checklistMode && checklistItems.length > 0}
<ul class="space-y-1" data-testid="note-checklist-preview">
{#each checklistItems.slice(0, 8) as item, index}
{#each sortedChecklistItems.slice(0, 8) as item}
<li class="flex items-center gap-2 text-sm {item.checked ? 'text-[var(--text-muted)] line-through' : 'text-[var(--text)]'}">
<input
type="checkbox"
checked={item.checked}
onclick={(e) => { e.stopPropagation(); toggleChecklistItem(index); }}
onclick={(e) => { e.stopPropagation(); toggleChecklistItem(item); }}
class="h-3.5 w-3.5 rounded border-[var(--border-subtle)] text-[var(--primary)] cursor-pointer"
data-testid="card-checklist-checkbox"
/>