diff --git a/.claude/guidelines/design-ux.md b/.claude/guidelines/design-ux.md index 260844dbc..6aba53434 100644 --- a/.claude/guidelines/design-ux.md +++ b/.claude/guidelines/design-ux.md @@ -346,6 +346,132 @@ Text: "Diese Aufgabe wird unwiderruflich gelöscht." | Abbrechen/Schließen | `Escape` | | Navigation | `Tab` / `Shift+Tab` | +### Listen-Navigation mit Tastatur + +In Listen (Tasks, Kontakte, Favoriten etc.) soll der Nutzer sich nahtlos per Tastatur bewegen können, ohne dass Fokus auf nicht-editierbare Elemente (Checkboxes, Drag-Handles) springt. + +**Prinzip: Zirkuläre Navigation zwischen Input und Liste** + +``` +InputBar → ArrowUp/Tab → Erster Listeneintrag + ↕ ArrowUp/Down/Tab/Shift+Tab +Letzter Eintrag → ArrowDown/Tab → InputBar +``` + +**Implementierung mit `contenteditable`:** + +```svelte + + + {item.title} + +``` + +**Keydown-Handler für Listen-Navigation:** + +```typescript +function handleKeydown(e: KeyboardEvent) { + if (e.key === 'Enter') { + e.preventDefault(); + currentRef?.blur(); // Speichert via onblur + } else if (e.key === 'Escape') { + currentRef.textContent = originalValue; // Verwerfen + currentRef?.blur(); + } else if (e.key === 'Tab' || e.key === 'ArrowDown' || e.key === 'ArrowUp') { + const direction = e.key === 'ArrowUp' || (e.key === 'Tab' && e.shiftKey) ? -1 : 1; + e.preventDefault(); + // Alle editierbaren Elemente auf der Seite sammeln + const allEditable = Array.from( + document.querySelectorAll('.item-title[contenteditable]') + ); + const currentIndex = allEditable.indexOf(currentRef!); + const next = allEditable[currentIndex + direction]; + currentRef?.blur(); + if (next) { + next.focus(); + } else { + // Am Rand der Liste: Fokus zur InputBar + document.querySelector('.quick-input-bar input')?.focus(); + } + } +} +``` + +**Von der InputBar in die Liste (Page-Level Handler):** + +```svelte + { + const target = e.target as HTMLElement; + if (target.closest('.quick-input-bar') && (e.key === 'ArrowUp' || e.key === 'Tab')) { + const first = document.querySelector('.item-title[contenteditable]'); + if (first) { + e.preventDefault(); + first.focus(); + } + } +}} /> +``` + +**Regeln:** + +- `contenteditable` statt Input-Toggle: Cursor landet direkt an Klick-Position +- Kein visueller Unterschied zwischen Lese- und Edit-Modus (kein Border, kein Hintergrund) +- Speichern via `blur`-Event (Auto-Save), nicht via explizitem Save-Button +- ArrowDown/Up navigiert vertikal, Tab/Shift+Tab ebenfalls (gleiche Richtung) +- Am Listenende/-anfang springt Fokus zurück zur InputBar (zirkulär) +- Hover-Effekte auf Listeneinträgen vermeiden (ruhige UI) + +### Inline-Editing mit contenteditable + +**Bevorzuge `contenteditable` statt Input-Toggle** für Texte, die direkt in der Ansicht editiert werden. + +| Aspekt | Input-Toggle | contenteditable | +| -------------------- | ------------------------------ | ---------------------------- | +| Klicks zum Editieren | 2 (aktivieren + positionieren) | 1 (Cursor an Klick-Position) | +| DOM-Wechsel | `` ↔ `` | Keiner | +| Mehrzeilig | Braucht `