diff --git a/.planning/STATE.md b/.planning/STATE.md
index d079821..32e3709 100644
--- a/.planning/STATE.md
+++ b/.planning/STATE.md
@@ -484,6 +484,7 @@ Gerettet aus `.continue-here.md`. Relevant fuer die noch offenen Live-Tests.
| 260929-if2 | **Erinnerungen-Widget (Reminder).** Modell `Reminder` + RLS, API /reminders (anlegen/listen/bearbeiten/loeschen/erledigt/snooze, 409/404-Regeln), E-Mail-Scheduler alle 30 s mit Claim-once + max. 3 Versuche, globaler ReminderNotifier (Browser-Notification, Desktop via Tauri-Notification mit Laufzeit-Capability nur fuer die Server-Origin, Pattern escaped + vorab geprueft). Verifier human_needed (Windows-Toast offen); Browser dunkel bestanden inkl. echter Mail ueber MailHog. api 1570, web 1069, cargo 57. Nebenbei: eigene Module ohne Kopfzeile (cd1f8f6), Update-Klick prueft frisch (41d00a3). | 2026-09-29 | 325c5dd,709b41a,6879c75 | [260929-if2-reminder-widget-mit-benachrichtigung](./quick/260929-if2-reminder-widget-mit-benachrichtigung/) |
| 260929-lh3 | **Favoriten: eigene Symbol-Adresse wirkt.** Neue iconUrl ersetzt Upload + bumpt iconVersion; iconUrl wird auch gespeichert, wenn nur der Browser sie laden kann (kein 422 mehr, nur Formpruefung); Kachel: Proxy -> iconUrl direkt -> origin/favicon -> Buchstabe; Discovery liest auch aus Nicht-2xx-Seiten (docuvita 400). | 2026-09-29 | 7188c5b,b15c746,0e72ad4 | [260929-lh3-favoriten-eigenes-symbol-wirkt-nicht](./quick/260929-lh3-favoriten-eigenes-symbol-wirkt-nicht/) |
| 261001-cxo | Desktop-Client: Links mit target=_blank (Favoriten) oeffnen jetzt im System-Browser (DesktopExternalLinks -> window.open) | 2026-10-01 | 61a971c | [261001-cxo](./quick/261001-cxo-desktop-client-links-mit-target-blank-oe/) |
+| 261001-g68 | Erinnerung: Cursor sprang beim Schreiben der Beschreibung in den Titel (Fokus-Effekt hing an inline onClose, Kachel zeichnet alle 10 s neu) – Fokus nur beim Oeffnen | 2026-10-01 | siehe git log | [261001-g68](./quick/261001-g68-erinnerung-cursor-springt-aus-beschreibu/) |
## Deferred Items
diff --git a/.planning/quick/261001-g68-erinnerung-cursor-springt-aus-beschreibu/261001-g68-PLAN.md b/.planning/quick/261001-g68-erinnerung-cursor-springt-aus-beschreibu/261001-g68-PLAN.md
new file mode 100644
index 0000000..48a0f22
--- /dev/null
+++ b/.planning/quick/261001-g68-erinnerung-cursor-springt-aus-beschreibu/261001-g68-PLAN.md
@@ -0,0 +1,14 @@
+---
+quick_id: 261001-g68
+description: "Erinnerung: Cursor springt aus Beschreibung in Titel"
+date: 2026-10-01
+---
+
+# Erinnerung: Cursor springt aus Beschreibung in Titel
+
+**Befund:** `ReminderFormModal` setzte den Fokus auf den Titel im selben Effekt wie den Escape-Listener, Abhaengigkeit `[onClose]`. `onClose` ist in der Kachel eine Inline-Funktion; die Kachel zeichnet alle 10 s neu (NOW_TICK_MS) und bei jedem Neuladen → Effekt laeuft erneut → Cursor springt in den Titel (User: beim Schreiben, und bei Loeschen-Taste in leerer Beschreibung).
+
+## Task 1
+- Fokus-Effekt nur beim Oeffnen (`[]`), Escape-Listener ueber `onCloseRef`.
+- Test im Widget: Formular oeffnen, Beschreibung fokussieren, 30 s Takt → Fokus bleibt.
+- CHANGELOG „Unveröffentlicht → Behoben“.
diff --git a/.planning/quick/261001-g68-erinnerung-cursor-springt-aus-beschreibu/261001-g68-SUMMARY.md b/.planning/quick/261001-g68-erinnerung-cursor-springt-aus-beschreibu/261001-g68-SUMMARY.md
new file mode 100644
index 0000000..9100ad7
--- /dev/null
+++ b/.planning/quick/261001-g68-erinnerung-cursor-springt-aus-beschreibu/261001-g68-SUMMARY.md
@@ -0,0 +1,10 @@
+---
+quick_id: 261001-g68
+status: complete
+date: 2026-10-01
+---
+
+# Summary
+- `reminder-form-modal.tsx`: Fokus auf Titel nur einmal beim Oeffnen; Escape ueber Ref statt `[onClose]`-Abhaengigkeit.
+- Neuer Test in `reminder-widget.test.tsx` – schlaegt ohne Fix fehl, mit Fix gruen; 28/28 Erinnerungs-Tests, tsc, biome sauber.
+- Andere Dialoge mit `[onClose]`-Fokus (Widget-Katalog, Bilderrahmen-Lightbox) fokussieren nur den Dialog ohne Eingabefelder – nicht betroffen.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8fc988d..94a54da 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,7 @@ Diese Liste beschreibt in einfachen Worten, was sich von Version zu Version an T
### Behoben
- Desktop-App: Favoriten und andere Links, die sich in einem neuen Fenster öffnen (etwa „In neuem Tab öffnen“ oder Quellen im Ausschreibungs-Radar), öffnen sich jetzt in Ihrem normalen Browser. Bisher passierte beim Klick in der Desktop-App nichts.
+- Erinnerungen: Beim Schreiben der Beschreibung springt der Cursor nicht mehr in die Titelzeile zurück. Bisher passierte das alle paar Sekunden, weil sich die Kachel regelmäßig neu aufbaut.
## 1.9.0 – 2026-09-30
diff --git a/apps/web/src/components/dashboard/widgets/reminder-form-modal.tsx b/apps/web/src/components/dashboard/widgets/reminder-form-modal.tsx
index e76e090..cb70069 100644
--- a/apps/web/src/components/dashboard/widgets/reminder-form-modal.tsx
+++ b/apps/web/src/components/dashboard/widgets/reminder-form-modal.tsx
@@ -65,14 +65,23 @@ export function ReminderFormModal({
const [error, setError] = useState(null);
const titleRef = useRef(null);
+ // Fokus nur EINMAL beim Oeffnen (quick-261001-g68): `onClose` kommt aus der
+ // Kachel als neue Funktion bei jedem Neuzeichnen — die Kachel zeichnet alle
+ // 10 s neu (NOW_TICK_MS). Hing der Fokus mit am `onClose`-Effekt, sprang der
+ // Cursor beim Schreiben der Beschreibung immer wieder in den Titel.
useEffect(() => {
titleRef.current?.focus();
+ }, []);
+
+ const onCloseRef = useRef(onClose);
+ onCloseRef.current = onClose;
+ useEffect(() => {
const onKey = (e: KeyboardEvent) => {
- if (e.key === 'Escape') onClose();
+ if (e.key === 'Escape') onCloseRef.current();
};
document.addEventListener('keydown', onKey);
return () => document.removeEventListener('keydown', onKey);
- }, [onClose]);
+ }, []);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
diff --git a/apps/web/src/components/dashboard/widgets/reminder-widget.test.tsx b/apps/web/src/components/dashboard/widgets/reminder-widget.test.tsx
index f7d5695..d565429 100644
--- a/apps/web/src/components/dashboard/widgets/reminder-widget.test.tsx
+++ b/apps/web/src/components/dashboard/widgets/reminder-widget.test.tsx
@@ -349,6 +349,32 @@ describe('ReminderWidget — Faelligkeit ohne Neuladen', () => {
});
});
+describe('ReminderWidget — Formular behaelt den Fokus (quick-261001-g68)', () => {
+ afterEach(() => {
+ vi.useRealTimers();
+ });
+
+ it('der 10-s-Takt der Kachel holt den Cursor nicht aus der Beschreibung zurueck in den Titel', async () => {
+ vi.useFakeTimers();
+ vi.setSystemTime(new Date('2026-09-29T12:00:00.000Z'));
+ mockList.mockResolvedValue([]);
+ render();
+ await act(async () => {
+ await vi.advanceTimersByTimeAsync(0);
+ });
+ fireEvent.click(screen.getByText('reminder.add'));
+ expect(document.activeElement).toBe(screen.getByLabelText('reminder.titleLabel'));
+
+ const description = screen.getByLabelText('reminder.descriptionLabel');
+ description.focus();
+ fireEvent.change(description, { target: { value: 'Unterlagen mitnehmen' } });
+ await act(async () => {
+ await vi.advanceTimersByTimeAsync(30_000);
+ });
+ expect(document.activeElement).toBe(description);
+ });
+});
+
describe('ReminderWidget — Spaeter erinnern kurz nach Mitternacht', () => {
afterEach(() => {
vi.useRealTimers();