diff --git a/README.md b/README.md
index f984626..903c04b 100644
--- a/README.md
+++ b/README.md
@@ -88,7 +88,7 @@ The date, storage, rollover, task and undo logic lives in `src/lib/` as plain mo
### Managing Tasks
- **Add a task**: Type in the input field and press Enter
- **Complete a task**: Click the checkbox next to the task
-- **Delete a task**: Hover over a task and click the delete icon, or press `Delete` with the task focused
+- **Delete a task**: Click the delete icon on the task (it shows on hover, and is always visible on touch), or press `Delete` with the task focused
- **Undo a delete**: Press `Cmd/Ctrl+Z`. The task returns to where it was
- **Reorder tasks**: Drag with a mouse, long-press then drag on touch, or focus a task and press `Alt+↑`/`Alt+↓`
- **Clear input**: Press Escape while the input is focused
diff --git a/src/App.svelte b/src/App.svelte
index 5cda81d..6fbd9c7 100644
--- a/src/App.svelte
+++ b/src/App.svelte
@@ -84,6 +84,19 @@
darkMode = !darkMode;
}
+ // Svelte's transitions are driven in JavaScript, so the CSS media query in
+ // style.css cannot reach them. Read the same preference here and collapse the
+ // durations. The lift on a dragged card stays: it tracks the pointer rather
+ // than playing at you, and losing it would make dragging harder to follow.
+ const motionQuery = window.matchMedia('(prefers-reduced-motion: reduce)');
+ let reduceMotion = $state(motionQuery.matches);
+
+ const flyIn = (index) =>
+ reduceMotion ? { duration: 0 } : { y: -10, duration: 300, delay: index * 30, easing: cubicOut };
+
+ const flyOut = (index) =>
+ reduceMotion ? { duration: 0 } : { x: 30, opacity: 0, duration: 250, delay: index * 20, easing: cubicOut };
+
let fileInput;
let status = $state('');
let statusIsError = $state(false);
@@ -399,6 +412,10 @@
}, msUntilNextMidnight(new Date()));
}
+ function handleMotionPreference(event) {
+ reduceMotion = event.matches;
+ }
+
function handleVisibility() {
if (document.visibilityState === 'visible') runRollover();
}
@@ -426,11 +443,13 @@
scheduleMidnight();
document.addEventListener('visibilitychange', handleVisibility);
window.addEventListener('focus', runRollover);
+ motionQuery.addEventListener('change', handleMotionPreference);
return () => {
clearTimeout(midnightTimer);
document.removeEventListener('visibilitychange', handleVisibility);
window.removeEventListener('focus', runRollover);
+ motionQuery.removeEventListener('change', handleMotionPreference);
};
});
@@ -518,7 +537,7 @@