Compare commits

...

2 Commits

Author SHA1 Message Date
Julien Calixte
afa9a2f008 fix(todo): smoothly collapse rows on filter leave/enter
Some checks failed
CI / verify (push) Failing after 7s
Switch the TransitionGroup animation from in-flow opacity+translate to
the grid-template-rows 1fr → 0fr pattern so a leaving row's height
shrinks during the transition. Avoids the post-animation snap that
happened when the DOM nodes were removed and the surrounding gap
suddenly closed.
2026-06-13 22:21:35 +02:00
Julien Calixte
bff3db79f9 style(todo): add plus/at icons to project and context chips
Aligns the baseline of +project and @context chips with due:/rec: chips
which already render Tabler SVG prefixes. Without an icon the text-only
prefix sat a few pixels off vertically.
2026-06-13 22:21:29 +02:00
2 changed files with 63 additions and 23 deletions

View File

@@ -268,7 +268,24 @@ watch(
class="todo-chip badge badge-soft badge-primary mx-0.5" class="todo-chip badge badge-soft badge-primary mx-0.5"
@click.stop @click.stop
> >
+{{ seg.value }} <svg
xmlns="http://www.w3.org/2000/svg"
class="icon icon-tabler icon-tabler-plus"
width="14"
height="14"
viewBox="0 0 24 24"
stroke-width="2"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path d="M12 5l0 14" />
<path d="M5 12l14 0" />
</svg>
{{ seg.value }}
<button <button
v-if="canEdit" v-if="canEdit"
class="todo-chip-close" class="todo-chip-close"
@@ -300,7 +317,28 @@ watch(
class="todo-chip badge badge-soft badge-secondary mx-0.5" class="todo-chip badge badge-soft badge-secondary mx-0.5"
@click.stop @click.stop
> >
@{{ seg.value }} <svg
xmlns="http://www.w3.org/2000/svg"
class="icon icon-tabler icon-tabler-at"
width="14"
height="14"
viewBox="0 0 24 24"
stroke-width="1.75"
stroke="currentColor"
fill="none"
stroke-linecap="round"
stroke-linejoin="round"
aria-hidden="true"
>
<path stroke="none" d="M0 0h24v24H0z" fill="none" />
<path
d="M12 12m-4 0a4 4 0 1 0 8 0a4 4 0 1 0 -8 0"
/>
<path
d="M16 12v1.5a2.5 2.5 0 0 0 5 0v-1.5a9 9 0 1 0 -5.5 8.28"
/>
</svg>
{{ seg.value }}
<button <button
v-if="canEdit" v-if="canEdit"
class="todo-chip-close" class="todo-chip-close"

View File

@@ -388,12 +388,14 @@ const createTodoFile = async () => {
<TransitionGroup name="todo" tag="ul" class="todo-list"> <TransitionGroup name="todo" tag="ul" class="todo-list">
<li v-for="entry in filteredEntries" :key="entry.index"> <li v-for="entry in filteredEntries" :key="entry.index">
<div class="todo-li-inner">
<todo-txt-item <todo-txt-item
:task="entry.line" :task="entry.line"
:can-edit="canPush" :can-edit="canPush"
@update="(t) => updateTask(entry.index, t)" @update="(t) => updateTask(entry.index, t)"
@delete="deleteTask(entry.index)" @delete="deleteTask(entry.index)"
/> />
</div>
</li> </li>
</TransitionGroup> </TransitionGroup>
@@ -431,35 +433,35 @@ const createTodoFile = async () => {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 0.25rem; gap: 0.25rem;
position: relative;
li { li {
list-style: none; list-style: none;
// Use grid-template-rows 1fr 0fr so the row's height (and therefore
// the surrounding gap) collapses smoothly during leave instead of
// snapping closed when the DOM node is removed.
display: grid;
grid-template-rows: 1fr;
} }
} }
.todo-li-inner {
overflow: hidden;
min-height: 0;
}
.todo-enter-active, .todo-enter-active,
.todo-leave-active { .todo-leave-active {
transition: transition:
opacity 180ms ease, opacity 180ms ease,
transform 220ms ease; transform 220ms ease,
} grid-template-rows 220ms ease;
.todo-enter-from {
opacity: 0;
transform: translateX(-12px);
} }
.todo-enter-from,
.todo-leave-to { .todo-leave-to {
opacity: 0; opacity: 0;
transform: translateX(12px); transform: translateX(-12px);
} grid-template-rows: 0fr;
// Take the leaving item out of layout flow so the rest of the list
// slides up smoothly via .todo-move instead of jumping.
.todo-leave-active {
position: absolute;
width: 100%;
} }
.todo-move { .todo-move {