diff --git a/docs/superpowers/plans/2026-03-31-shopping-swipe-gestures.md b/docs/superpowers/plans/2026-03-31-shopping-swipe-gestures.md new file mode 100644 index 0000000..4bc423f --- /dev/null +++ b/docs/superpowers/plans/2026-03-31-shopping-swipe-gestures.md @@ -0,0 +1,476 @@ +# Shopping Swipe Gestures Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Add left-swipe-to-toggle and right-swipe-to-delete touch gestures to Shopping list items on mobile, replacing the visible × delete button on small screens. + +**Architecture:** Shared swipe base CSS is moved from `tasks.css` to `layout.css` so both modules can use it. Shopping-specific styles (delete reveal, mobile button hiding) go in `shopping.css`. `shopping.js` wraps each item in a `swipe-row` and registers touch handlers via a new `wireSwipeGestures()` function, called after every list re-render. + +**Tech Stack:** Vanilla JS (ES modules), Touch Events API, CSS custom properties, Node.js built-in test runner (regression tests only — no DOM test framework in this project). + +--- + +## File Map + +| File | Change | +|------|--------| +| `public/styles/tasks.css` | Remove `.swipe-row`, `.swipe-reveal`, `.swipe-reveal--done` (moved to layout.css) | +| `public/styles/layout.css` | Add moved shared swipe styles + `.swipe-reveal--done` | +| `public/styles/shopping.css` | Add `.swipe-reveal--delete`, `.swipe-row .shopping-item`, `.swipe-row--swiping .shopping-item`, mobile hide for `.item-delete` | +| `public/pages/shopping.js` | Wrap `renderItem()` output in swipe-row, add `wireSwipeGestures(container)`, call it from `updateItemsList()` | + +--- + +### Task 1: Move shared swipe CSS from tasks.css to layout.css + +**Files:** +- Modify: `public/styles/tasks.css` (lines 170–229) +- Modify: `public/styles/layout.css` (append before Print section) + +- [ ] **Step 1: Remove base swipe styles from tasks.css** + +In `public/styles/tasks.css`, delete the block from `/* Swipe-Wrapper (Mobil-Gesten) */` through `.swipe-reveal--done { ... }` (lines 170–216). Keep only the task-specific rules that follow: + +```css +/* Kein Margin mehr am Task-Card selbst (übernimmt swipe-row) */ +.swipe-row .task-card { + margin-bottom: 0; + border-radius: var(--radius-md); + position: relative; + z-index: 1; + will-change: transform; +} + +/* Rechts hinter der Karte = Bearbeiten (Swipe nach rechts) */ +.swipe-reveal--edit { + left: 0; + background-color: var(--color-accent); + color: #fff; + border-radius: var(--radius-md) 0 0 var(--radius-md); +} + +/* Touch-Feedback: leichte Hervorhebung während Swipe */ +.swipe-row--swiping .task-card { + box-shadow: var(--shadow-lg); +} +``` + +Add a comment header so the section remains clear: + +```css +/* -------------------------------------------------------- + * Swipe-Wrapper — Task-spezifische Styles + * Basis-Styles (.swipe-row, .swipe-reveal, .swipe-reveal--done) + * liegen in layout.css + * -------------------------------------------------------- */ +``` + +- [ ] **Step 2: Add shared swipe styles to layout.css** + +In `public/styles/layout.css`, find the Print section (`/* Print-Styles */`) and insert the following block **directly before it**: + +```css +/* -------------------------------------------------------- + * Swipe-Wrapper — Gemeinsame Basis (Tasks + Shopping) + * Modul-spezifische Styles (.swipe-reveal--edit, .swipe-reveal--delete, + * .swipe-row .task-card, .swipe-row .shopping-item) liegen in den Modul-CSS. + * -------------------------------------------------------- */ +.swipe-row { + position: relative; + overflow: hidden; + border-radius: var(--radius-md); + margin-bottom: var(--space-2); + /* Verhindert ungewolltes Flackern auf iOS */ + -webkit-backface-visibility: hidden; +} + +/* Reveal-Panels hinter der Karte */ +.swipe-reveal { + position: absolute; + top: 0; + bottom: 0; + width: 50%; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: var(--space-1); + font-size: var(--text-xs); + font-weight: var(--font-weight-semibold); + opacity: 0; + pointer-events: none; + z-index: 0; + transition: opacity 0.05s linear; +} + +/* Gemeinsam: Erledigt / Abhaken (Swipe nach links) */ +.swipe-reveal--done { + right: 0; + background-color: var(--color-success); + color: #fff; + border-radius: 0 var(--radius-md) var(--radius-md) 0; +} +``` + +- [ ] **Step 3: Run regression tests** + +```bash +npm test +``` + +Expected: `# pass 12` and `# fail 0` + +- [ ] **Step 4: Verify tasks swipe still works visually** + +Open the app in a browser (or mobile DevTools touch emulation), go to Tasks list, swipe an item left and right. The green "Erledigt" and blue "Bearbeiten" panels must still appear correctly. + +- [ ] **Step 5: Commit** + +```bash +git add public/styles/tasks.css public/styles/layout.css +git commit -m "refactor: move shared swipe CSS from tasks.css to layout.css" +``` + +--- + +### Task 2: Add shopping-specific swipe CSS + +**Files:** +- Modify: `public/styles/shopping.css` + +- [ ] **Step 1: Find the correct insertion point in shopping.css** + +In `public/styles/shopping.css`, locate the section for `.shopping-item` styles. The new swipe styles go **after** the existing `.shopping-item` block. + +- [ ] **Step 2: Add the styles** + +Append the following after the existing `.shopping-item` rules in `public/styles/shopping.css`: + +```css +/* -------------------------------------------------------- + * Swipe-Wrapper — Shopping-spezifische Styles + * -------------------------------------------------------- */ + +/* Kein Margin mehr am shopping-item selbst (übernimmt swipe-row) */ +.swipe-row .shopping-item { + margin-bottom: 0; + border-radius: var(--radius-md); + position: relative; + z-index: 1; + will-change: transform; +} + +/* Rechts hinter der Karte = Löschen (Swipe nach rechts) */ +.swipe-reveal--delete { + left: 0; + background-color: var(--color-danger); + color: #fff; + border-radius: var(--radius-md) 0 0 var(--radius-md); +} + +/* Touch-Feedback: leichte Hervorhebung während Swipe */ +.swipe-row--swiping .shopping-item { + box-shadow: var(--shadow-lg); +} + +/* × Löschen-Button auf Mobile ausblenden — Swipe übernimmt */ +@media (max-width: 1023px) { + .item-delete { + display: none; + } +} +``` + +- [ ] **Step 3: Run regression tests** + +```bash +npm test +``` + +Expected: `# pass 12` and `# fail 0` + +- [ ] **Step 4: Commit** + +```bash +git add public/styles/shopping.css +git commit -m "feat: add shopping swipe CSS (delete reveal, mobile button hide)" +``` + +--- + +### Task 3: Wrap renderItem with swipe-row in shopping.js + +**Files:** +- Modify: `public/pages/shopping.js` + +- [ ] **Step 1: Update renderItem()** + +Find `function renderItem(item)` in `public/pages/shopping.js` (currently returns a `.shopping-item` div). Replace the entire function with: + +```js +function renderItem(item) { + const isDone = Boolean(item.is_checked); + return ` +