diff --git a/docs/wiki/2.05-Manage-Scheduled-Tasks.md b/docs/wiki/2.05-Manage-Scheduled-Tasks.md
index 48183b5248..847e445b5d 100755
--- a/docs/wiki/2.05-Manage-Scheduled-Tasks.md
+++ b/docs/wiki/2.05-Manage-Scheduled-Tasks.md
@@ -37,7 +37,7 @@ The task is scheduled immediately and the menu closes. To pick any date or set a
2. In **Remind at**, choose when you want to be reminded. Options in the app are: **Never**, **when it starts**, **5 minutes before it starts**, **10 minutes before it starts**, **15 minutes before it starts**, **30 minutes before it starts**, **1 hour before it starts**.
3. Click **Schedule**.
-When a task reminder dialog appears, choose an explicit action such as snooze, unschedule, dismiss the reminder, add to today, start, or done. Clicking outside the dialog or pressing Escape does not dismiss the reminder.
+When a task reminder dialog appears, choose an action such as snooze, unschedule, dismiss the reminder, add to today, start, or done. Clicking outside the dialog or pressing Escape just closes it: scheduled task reminders stay active and pop up again shortly until you act on them, while deadline reminders are cleared on close.
## Remove Scheduling from a Task
diff --git a/e2e/tests/reminders/reminders-deadline.spec.ts b/e2e/tests/reminders/reminders-deadline.spec.ts
index 1a74fb54d3..aca0c6ac40 100644
--- a/e2e/tests/reminders/reminders-deadline.spec.ts
+++ b/e2e/tests/reminders/reminders-deadline.spec.ts
@@ -83,8 +83,12 @@ test.describe('Deadline Reminders', () => {
const dueForText = await dueForEl.textContent();
expect(dueForText!.trim().length).toBeGreaterThan(0);
- // Dismiss by marking the task as done
- await page.locator(REMINDER_DIALOG).locator('button:has-text("Done")').click();
+ // Dismiss by marking the task as done (in the overflow "More actions" menu)
+ await page
+ .locator(REMINDER_DIALOG)
+ .locator('button[aria-label="More actions"]')
+ .click();
+ await page.getByRole('menuitem', { name: 'Done' }).click();
// Wait for the reminder dialog to close
await page.locator(REMINDER_DIALOG).waitFor({ state: 'hidden', timeout: 10000 });
@@ -94,7 +98,7 @@ test.describe('Deadline Reminders', () => {
await expect(page.locator(REMINDER_DIALOG)).not.toBeVisible();
});
- test('should require an explicit action for the deadline reminder dialog', async ({
+ test('should dismiss the deadline reminder dialog on Escape without re-triggering', async ({
page,
workViewPage,
testPrefix,
@@ -146,14 +150,9 @@ test.describe('Deadline Reminders', () => {
const reminderDialog = page.locator(REMINDER_DIALOG);
await expect(reminderDialog).toBeVisible();
- // ESC and backdrop clicks must not passively dismiss the reminder dialog.
+ // Pressing Escape dismisses the reminder (clearing the reminder timestamp
+ // while keeping the task and its deadline) and closes the dialog.
await page.keyboard.press('Escape');
- await expect(reminderDialog).toBeVisible();
-
- await page.locator('.cdk-overlay-backdrop').last().click({ force: true });
- await expect(reminderDialog).toBeVisible();
-
- await reminderDialog.locator('button:has-text("Done")').click();
await reminderDialog.waitFor({ state: 'hidden', timeout: 10000 });
// Poll over a window longer than the 10s reminder worker tick. If the
@@ -218,12 +217,12 @@ test.describe('Deadline Reminders', () => {
await page.waitForSelector(REMINDER_DIALOG_TASK_1, { state: 'visible' });
await expect(page.locator(REMINDER_DIALOG_TASK_1)).toContainText(taskTitle);
- // Click "Snooze" to open snooze menu, then "Reschedule until tomorrow"
- const snoozeBtn = page
+ // Open the overflow menu (the split-button dropdown right of snooze), then
+ // pick "Reschedule for tomorrow". The main snooze button snoozes 10m directly.
+ const snoozeMenuBtn = page
.locator(REMINDER_DIALOG)
- .locator('button:has(mat-icon:text("snooze"))')
- .first();
- await snoozeBtn.click();
+ .locator('button[aria-label="More actions"]');
+ await snoozeMenuBtn.click();
const rescheduleOption = page.locator(
'button[mat-menu-item]:has-text("Reschedule for tomorrow")',
diff --git a/src/app/features/reminder/reminder.module.spec.ts b/src/app/features/reminder/reminder.module.spec.ts
index 1479c789aa..f6c1b719ec 100644
--- a/src/app/features/reminder/reminder.module.spec.ts
+++ b/src/app/features/reminder/reminder.module.spec.ts
@@ -87,7 +87,7 @@ describe('ReminderModule dialog opening', () => {
});
});
- it('opens task reminder dialog without passive close paths', fakeAsync(() => {
+ it('opens task reminder dialog as dismissable (no disableClose)', fakeAsync(() => {
TestBed.inject(ReminderModule);
syncDone$.next();
@@ -96,7 +96,6 @@ describe('ReminderModule dialog opening', () => {
expect(matDialogSpy.open).toHaveBeenCalledOnceWith(DialogViewTaskRemindersComponent, {
restoreFocus: true,
- disableClose: true,
data: {
reminders: [reminder],
},
diff --git a/src/app/features/reminder/reminder.module.ts b/src/app/features/reminder/reminder.module.ts
index 739f2a0189..935d7a470e 100644
--- a/src/app/features/reminder/reminder.module.ts
+++ b/src/app/features/reminder/reminder.module.ts
@@ -188,7 +188,9 @@ export class ReminderModule {
} else {
this._matDialog.open(DialogViewTaskRemindersComponent, {
restoreFocus: true,
- disableClose: true,
+ // Backdrop click / Escape closes the dialog. Deadline reminders are
+ // cleared on destroy; scheduled reminders stay active and the worker
+ // re-shows them until the user acts on them.
data: {
reminders,
},
diff --git a/src/app/features/tasks/dialog-view-task-reminders/dialog-view-task-reminders.component.html b/src/app/features/tasks/dialog-view-task-reminders/dialog-view-task-reminders.component.html
index 8e6bd959fb..ad84f14521 100644
--- a/src/app/features/tasks/dialog-view-task-reminders/dialog-view-task-reminders.component.html
+++ b/src/app/features/tasks/dialog-view-task-reminders/dialog-view-task-reminders.component.html
@@ -49,64 +49,37 @@
}