From ccd46ebd7b91e39727c61c5c15a0194905550e7e Mon Sep 17 00:00:00 2001 From: callumalpass Date: Thu, 25 Jun 2026 17:26:14 +1000 Subject: [PATCH] fix reminder modal absolute tab --- docs/releases/unreleased.md | 1 + src/modals/ReminderModal.ts | 54 ++----------- styles/reminder-modal.css | 3 +- ...e-2079-reminder-modal-absolute-tab.test.ts | 75 +++++++++++++++++++ 4 files changed, 84 insertions(+), 49 deletions(-) create mode 100644 tests/unit/issues/issue-2079-reminder-modal-absolute-tab.test.ts diff --git a/docs/releases/unreleased.md b/docs/releases/unreleased.md index e5e027e7..6b905102 100644 --- a/docs/releases/unreleased.md +++ b/docs/releases/unreleased.md @@ -53,6 +53,7 @@ When a change has user-facing documentation, include a canonical tasknotes.dev l - (#2063) Fixed project autocomplete storing ambiguous project links without the selected note's folder path. Thanks to @chmac for reporting this. - (#2072) Fixed inline task links to headings so they show both the task title and heading instead of only the heading. Thanks to @spasche for reporting this. - (#2075) Fixed multiday Calendar events being clipped to one day when a Base is embedded in Reading view. Thanks to @ddevaal for reporting this. +- (#2079) Fixed the reminder modal's **Absolute** tab so it switches from relative fields to absolute date and time fields. Thanks to @JunwonYoon for reporting this and identifying the CSS specificity issue. ## Changed diff --git a/src/modals/ReminderModal.ts b/src/modals/ReminderModal.ts index f4f57d05..e3e8bbbf 100644 --- a/src/modals/ReminderModal.ts +++ b/src/modals/ReminderModal.ts @@ -6,6 +6,7 @@ import { attachDateInputBehavior } from "../ui/dateInputBehavior"; import { createTaskNotesLogger } from "../utils/tasknotesLogger"; const tasknotesLogger = createTaskNotesLogger({ tag: "Modals/ReminderModal" }); +const REMINDER_FIELDS_HIDDEN_CLASS = "reminder-modal__fields--hidden"; export class ReminderModal extends Modal { private plugin: TaskNotesPlugin; @@ -440,7 +441,9 @@ export class ReminderModal extends Modal { }); // Absolute reminder fields - const absoluteContainer = form.createDiv({ cls: "absolute-fields" }); + const absoluteContainer = form.createDiv({ + cls: `absolute-fields ${REMINDER_FIELDS_HIDDEN_CLASS}`, + }); new Setting(absoluteContainer).setName("Date").addText((text) => { text.setPlaceholder("Yyyy-mm-dd") @@ -541,53 +544,8 @@ export class ReminderModal extends Modal { const relativeFields = form.querySelector(".relative-fields") as HTMLElement; const absoluteFields = form.querySelector(".absolute-fields") as HTMLElement; - if (type === "relative") { - relativeFields.classList.remove( - "tn-static-display-flex-4d51fc62", - "tn-static-display-flex-75816cae", - "tn-static-display-flex-8bb39979", - "tn-static-display-inline-block-60e32dcb", - "tn-static-display-inline-cccfa456", - "tn-static-display-inline-flex-f984c520", - "tn-static-display-none-6b99de8b", - "tn-static-min-height-800px-997b4c8c" - ); - relativeFields.classList.add("tn-static-display-block-2a1b75c9"); - absoluteFields.classList.remove( - "tn-static-display-block-2a1b75c9", - "tn-static-display-flex-4d51fc62", - "tn-static-display-flex-75816cae", - "tn-static-display-flex-8bb39979", - "tn-static-display-inline-block-60e32dcb", - "tn-static-display-inline-cccfa456", - "tn-static-display-inline-flex-f984c520", - "tn-static-min-height-800px-997b4c8c" - ); - absoluteFields.classList.add("tn-static-display-none-6b99de8b"); - } else { - relativeFields.classList.remove( - "tn-static-display-block-2a1b75c9", - "tn-static-display-flex-4d51fc62", - "tn-static-display-flex-75816cae", - "tn-static-display-flex-8bb39979", - "tn-static-display-inline-block-60e32dcb", - "tn-static-display-inline-cccfa456", - "tn-static-display-inline-flex-f984c520", - "tn-static-min-height-800px-997b4c8c" - ); - relativeFields.classList.add("tn-static-display-none-6b99de8b"); - absoluteFields.classList.remove( - "tn-static-display-flex-4d51fc62", - "tn-static-display-flex-75816cae", - "tn-static-display-flex-8bb39979", - "tn-static-display-inline-block-60e32dcb", - "tn-static-display-inline-cccfa456", - "tn-static-display-inline-flex-f984c520", - "tn-static-display-none-6b99de8b", - "tn-static-min-height-800px-997b4c8c" - ); - absoluteFields.classList.add("tn-static-display-block-2a1b75c9"); - } + relativeFields.classList.toggle(REMINDER_FIELDS_HIDDEN_CLASS, type !== "relative"); + absoluteFields.classList.toggle(REMINDER_FIELDS_HIDDEN_CLASS, type !== "absolute"); } private createReminder( diff --git a/styles/reminder-modal.css b/styles/reminder-modal.css index f75bfad0..c901e99e 100644 --- a/styles/reminder-modal.css +++ b/styles/reminder-modal.css @@ -321,7 +321,8 @@ body.is-mobile .tasknotes-plugin .reminder-modal__action-btn svg { margin-top: var(--size-4-2); } -.tasknotes-plugin .absolute-fields { +.tasknotes-plugin .relative-fields.reminder-modal__fields--hidden, +.tasknotes-plugin .absolute-fields.reminder-modal__fields--hidden { display: none; } diff --git a/tests/unit/issues/issue-2079-reminder-modal-absolute-tab.test.ts b/tests/unit/issues/issue-2079-reminder-modal-absolute-tab.test.ts new file mode 100644 index 00000000..dc2afca3 --- /dev/null +++ b/tests/unit/issues/issue-2079-reminder-modal-absolute-tab.test.ts @@ -0,0 +1,75 @@ +import fs from "fs"; +import path from "path"; +import type { App } from "obsidian"; +import { ReminderModal } from "../../../src/modals/ReminderModal"; +import type { TaskInfo } from "../../../src/types"; +import { MockObsidian } from "../../helpers/obsidian-runtime"; + +const repoRoot = path.resolve(__dirname, "../../.."); + +function readRepoFile(relativePath: string): string { + return fs.readFileSync(path.join(repoRoot, relativePath), "utf8"); +} + +function createPlugin(app: App): any { + return { + app, + emitter: { + trigger: jest.fn(), + }, + }; +} + +function createTask(): TaskInfo { + return { + title: "Absolute reminder smoke", + path: "TaskNotes/absolute-reminder-smoke.md", + status: "open", + priority: "normal", + due: "2026-06-26", + scheduled: "2026-06-25", + reminders: [], + } as TaskInfo; +} + +function findTypeTab(container: HTMLElement, label: string): HTMLButtonElement { + const tab = Array.from( + container.querySelectorAll(".reminder-modal__type-tab") + ).find((button) => button.textContent === label); + + if (!tab) { + throw new Error(`Could not find ${label} reminder type tab`); + } + + return tab; +} + +describe("Issue #2079: Reminder modal absolute tab visibility", () => { + it("toggles relative and absolute fields with a modal-specific hidden class", () => { + const app = MockObsidian.createMockApp() as unknown as App; + const modal = new ReminderModal(app, createPlugin(app), createTask(), jest.fn()); + const container = document.createElement("div"); + + (modal as any).renderAddReminderForm(container); + + const relativeFields = container.querySelector(".relative-fields") as HTMLElement; + const absoluteFields = container.querySelector(".absolute-fields") as HTMLElement; + + expect(relativeFields.classList.contains("reminder-modal__fields--hidden")).toBe(false); + expect(absoluteFields.classList.contains("reminder-modal__fields--hidden")).toBe(true); + + findTypeTab(container, "Absolute").click(); + + expect(relativeFields.classList.contains("reminder-modal__fields--hidden")).toBe(true); + expect(absoluteFields.classList.contains("reminder-modal__fields--hidden")).toBe(false); + }); + + it("hides reminder field groups with scoped CSS instead of an unconditional absolute field rule", () => { + const css = readRepoFile("styles/reminder-modal.css"); + + expect(css).toMatch( + /\.tasknotes-plugin \.relative-fields\.reminder-modal__fields--hidden,\s*\.tasknotes-plugin \.absolute-fields\.reminder-modal__fields--hidden\s*\{[^}]*display:\s*none;/s + ); + expect(css).not.toMatch(/\.tasknotes-plugin \.absolute-fields\s*\{\s*display:\s*none;\s*\}/); + }); +});