docs: add shopping swipe gestures design spec

This commit is contained in:
Ulas
2026-03-31 12:38:27 +02:00
parent fd94c58fea
commit bf417c2144
@@ -0,0 +1,79 @@
# Shopping Swipe Gestures — Design Spec
**Date:** 2026-03-31
**Status:** Approved
## Scope
Add swipe gestures to Shopping list items on mobile. Notes and other modules are explicitly out of scope.
## Behaviour
| Gesture | Action | Reveal colour |
|---------|--------|---------------|
| Swipe left (> threshold) | Toggle checked/unchecked | Green (`--color-success`) |
| Swipe right (> threshold) | Delete item | Red (`--color-danger`) |
- Reveal label for left swipe: "Abhaken" (unchecked) or "Zurück" (already checked)
- Reveal label for right swipe: "Löschen" (always)
- Threshold, damping, and scroll-lock logic identical to `tasks.js`
- On swipe-right delete: optimistic DOM removal → `DELETE /api/v1/shopping/items/:id` → on error restore item and show danger toast
- On swipe-left toggle: optimistic DOM update (class toggle) → `PATCH /api/v1/shopping/items/:id` → on error revert and show danger toast
## CSS Changes
**`layout.css`** — receives shared swipe infrastructure (moved from `tasks.css`):
- `.swipe-row` base styles
- `.swipe-reveal` base styles
- `.swipe-reveal--done` (green, used by tasks and shopping)
**`tasks.css`** — retains only task-specific styles:
- `.swipe-row .task-card`
- `.swipe-reveal--edit` (blue, tasks only)
- `.swipe-row--swiping .task-card`
**`shopping.css`** — new shopping-specific styles:
- `.swipe-row .shopping-item`
- `.swipe-row--swiping .shopping-item`
- `.swipe-reveal--delete` (red, `--color-danger`)
- `@media (max-width: 1023px) .item-delete { display: none }`× button hidden on mobile, swipe replaces it
## JavaScript Changes (`shopping.js`)
### `renderItem(item)` → wrapped in swipe-row
```html
<div class="swipe-row" data-swipe-id="${item.id}" data-swipe-checked="${item.is_checked}">
<div class="swipe-reveal swipe-reveal--done">
<i data-lucide="check|rotate-ccw"></i>
<span>Abhaken|Zurück</span>
</div>
<div class="swipe-reveal swipe-reveal--delete">
<i data-lucide="trash-2"></i>
<span>Löschen</span>
</div>
<!-- existing .shopping-item content, item-delete button kept for desktop -->
</div>
```
### New `wireSwipeGestures(container)`
Registers `touchstart` / `touchmove` (passive: false) / `touchend` on each `.swipe-row` inside `#items-list`. Logic mirrors tasks.js:
1. `touchstart`: record `startX`, `startY`, clear `locked` flag
2. `touchmove`: determine swipe vs. vertical scroll via angle; once locked to swipe, translate card, fade-in appropriate reveal panel proportionally
3. `touchend`: if locked and `|dx| > SWIPE_THRESHOLD` trigger action; otherwise spring back
Constants (same as tasks.js):
- `SWIPE_THRESHOLD = 80` px
- `SWIPE_LOCK_VERT = 8` px
- `SWIPE_MAX_VERT = 10` px
Called from `renderContent()` after DOM update, alongside existing `wireAutocomplete` and `wireQuickAdd` calls. Also called from `rerenderItems()` after any state change that re-renders the list.
## Out of Scope
- Notes swipe gestures
- Any other module
- Undo toast after delete (delete is immediate; existing × button provided undo-less delete already)
- Desktop swipe via mouse/pointer events