Skip to content

fix(peek): restack a resumed prompt above modals opened during the peek - #2238

Merged
chhoumann merged 2 commits into
masterfrom
issue-2235
Oct 13, 2026
Merged

chhoumann merged 2 commits into
masterfrom
issue-2235

Conversation

@chhoumann

@chhoumann chhoumann commented Oct 13, 2026 •

Copy link
Copy Markdown
Owner

Why

When you peek at the note from a QuickAdd prompt, open another plugin's modal (here Full Calendar Remastered's New Event dialog), and then select Return, the prompt comes back under that modal. Obsidian stacks modals in DOM order. The prompt has the keyboard focus but you cannot see it, and Escape cancels the QuickAdd run. This is the "prompt buried behind other modals" part of #2235 and of #2234.

What changed

  • When a peeked prompt resumes, it moves its modal container to the end of its parent, above any modal that opened during the peek. This applies to the single prompt and to the one-page form.

Scope

Tradeoffs

  • Refusing Return while another modal is open would keep all stacks in agreement. But then a user would have to discard an unfinished dialog to finish the QuickAdd run.

Verification

  • Full Calendar Remastered 0.13.6 on Obsidian 1.14.4, peek, New Event, Return: before the fix, New Event covers the form. After the fix, the form is on top with the caret in Name. Screenshots are below.
  • New native E2E spec tests/e2e/prompt-peek-stacking.test.ts. On master it fails in both prompt kinds with expected 'covered by New Event' to be true. With the fix it passes 2/2. A unit test in InputPromptPeek.test.ts covers the same order for CI.
  • pnpm run lint passes. pnpm run test passes, 6881 tests.

Before: before

After: after

Refs #2235, #2234

A modal another plugin opens while a prompt is peeked stays on top after Return, so the prompt is hidden while it holds focus (#2235).
Returning to a peeked prompt only removed its hidden class. Obsidian stacks modals of equal z-index in DOM order, so a modal another plugin opened during the peek, such as Full Calendar Remastered's event dialog, covered the prompt while the prompt held the keyboard. Re-appending the prompt's container on resume puts it back on top.

Refs #2235, #2234
@chhoumann chhoumann linked an issue Oct 13, 2026 that may be closed by this pull request
@coderabbitai

coderabbitai Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 38b9f658-73a2-41bb-9e30-fe59f44cfa94
📥 Commits

Reviewing files that changed from the base of the PR and between 45cd3fb and 2a51c94.

📒 Files selected for processing: 3
  • src/gui/promptPeek/InputPromptPeek.test.ts
  • src/gui/promptPeek/InputPromptPeek.ts
  • tests/e2e/prompt-peek-stacking.test.ts

Included review availability: This review used your included allowance. Your plan provides up to 8 included reviews per hour; 6 remain after this review.

📝 Walkthrough

When a peeked prompt resumes, its container moves to the end of its parent’s DOM children before the prompt is shown. Unit and end-to-end tests verify stacking order and input behavior.

Changes: Prompt Peek Stacking

Layer / File(s) Summary
Restore prompt stacking
src/gui/promptPeek/InputPromptPeek.ts, src/gui/promptPeek/InputPromptPeek.test.ts
showModal() re-appends the prompt container before showing it. The unit test checks stacking order, focus, input value, and caret position.
Verify resumed prompt flow
tests/e2e/prompt-peek-stacking.test.ts
The end-to-end test covers both one-page input settings. It checks that the resumed prompt is on top, verifies the created note content, and confirms the other modal remains connected.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to 2a51c

The resumed prompt is restored above the sibling modal, with regression assertions for both prompt modes. No actionable merge-blocking issue is identified.

Pre-merge checks: Passed 5
Passed Passed checks: 5 passed
Check name Status Explanation
Docstring Coverage Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. Docstring coverage is scoped to functions touched by this diff. Analyzed 0 functions across 3…
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Description Check Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check Passed The title clearly and concisely describes the main change: restacking a resumed peeked prompt above modals opened during the peek.
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

A rabbit taps the prompt back in place,
Its field and caret keep their place.
The modal waits; the prompt sits high,
“Ada” hops in, notes say hello nearby.
The rabbit nods, then bounds away.

Comment @coderabbitai help to get the list of available commands.

@chhoumann

Copy link
Copy Markdown
Owner Author

What I tried to reproduce the blank one-page form from #2235. None of these showed a form without fields.

  • The reporter's choice: a capture with format Person: {{VALUE:Name}}, Phone: {{VALUE:Phone}} {{LINKCURRENT}} and One-page input set to Always. I ran it from a command while a note was open. The form showed both fields.
  • The same choice with six capture targets: the active file in a note leaf, in an empty leaf, and in a graph leaf, then Calendar/{{VALUE:Title}}, {{LINKCURRENT}}, and a folder. I ran each with Always and with Never, while a plain Obsidian modal with a focused input stayed open under the prompt. That is 12 runs on Obsidian 1.13.7 and 12 runs on 1.14.4. Each Always run showed a form with all fields, on top and with focus.
  • The real Full Calendar Remastered 0.13.6. The QuickAdd hotkey and Ctrl+P do nothing while its New Event dialog is open, because an Obsidian modal's scope swallows global hotkeys. So the reporter must have started QuickAdd first.
  • Start QuickAdd, peek, open New Event, then Return. This reproduces the buried prompt that this PR fixes. At 1600x1000 the dialog covers the whole form. On a different window size or theme, the border and buttons of the taller form could show around the dialog. That would look like a blank form with buttons, but I have not confirmed that.

The reporter mentions "OK" buttons. The one-page form's button is "Submit". "Ok" is on the single prompt.

@chhoumann

Copy link
Copy Markdown
Owner Author

Independent verification: PASS

Verified head 2a51c9465e3cc0c309ebd832735d096772eeca59 against base 45cd3fb030ab4d2c1b63ae8edad4f5d0f1180258 (master). Real Obsidian 1.13.7 on Linux in the isolated E2E vault, in a detached worktree. I did not write this code.

1. The PR's spec, parent against head. env -u DISPLAY .agents/run-e2e tests/e2e/prompt-peek-stacking.test.ts

At fc97462 (tests only, bug present) both cases fail at the check after Return:

AssertionError: expected 'covered by New Event' to be true // Object.is equality
 Test Files  1 failed (1)
      Tests  2 failed (2)

At 2a51c94 (fix):

 ✓ tests/e2e/prompt-peek-stacking.test.ts (2 tests) 768ms
 Test Files  1 passed (1)
      Tests  2 passed (2)

2. My own drive, not the spec. Driven through obsidian:e2e eval plus CDP input, with a Capture choice that writes Person: {{VALUE:Name}} to the active note, once with onePageInput always and once with never. Flow: open a note, run the choice, click Peek at note, open an Obsidian Modal titled "New Event" with a textarea, click Return on the chip.

At the head build, in both modes:

  • After Return, document.elementFromPoint at the focused field's centre is the field. Body order of modal containers is New Event, then the QuickAdd prompt.
  • Typing Ada over CDP and submitting (Ctrl+Enter for the form, Enter for the single prompt) writes Person: Ada\n# Event\n to the note.
  • The New Event modal is still open afterwards and closes cleanly.
  • A plain peek and Return with no other modal keeps the field value half written, the caret at 4, focus on the field, and the field on top.
  • dev:errors reports no errors.

The same script on the base build (45cd3fb) reports after Return: covered by New Event, with body order QuickAdd prompt, then New Event. So the drive sees the bug and the fix removes it.

3. Checks at 2a51c94. pnpm run test: 6881 passed, 28 skipped. pnpm run lint: clean (oxlint, svelte-policy, tsconfig check, svelte-check with 0 errors and 0 warnings).

The known accepted gaps (Android Back after Return, Ctrl/Cmd+Shift+E while another plugin's modal is open) were not exercised. Nothing worse was seen.

@chhoumann

Copy link
Copy Markdown
Owner Author

Independent verification, round 2: PASS

Verified the landing result of head 2a51c9465e3cc0c309ebd832735d096772eeca59 on the new base e17ee7c6d44aaed8d20bb565b56db29b188d3d13 (master after #2239). git merge-tree --write-tree e17ee7c6 2a51c946 and the local rebase commit 0ed8d4564735559220d89dfcbf53da8dfafb0baa both give tree 4a8452b398d6033e6973bd2edc5a4620cf585405. Real Obsidian 1.13.7 on Linux, plugin build 2.32.1, in a detached worktree with the isolated E2E vault. I did not write this code.

1. Both specs, parent against head. env -u DISPLAY .agents/run-e2e tests/e2e/prompt-peek-stacking.test.ts tests/e2e/peek-over-plugin-modal.test.ts

At 0ed8d456~1 (new master plus the PR's tests, no fix):

AssertionError: expected 'covered by New Event' to be true // Object.is equality
 Test Files  1 failed | 1 passed (2)
      Tests  2 failed | 2 passed (4)

At 0ed8d456 (landing tree):

 ✓ tests/e2e/prompt-peek-stacking.test.ts (2 tests) 2717ms
 ✓ tests/e2e/peek-over-plugin-modal.test.ts (2 tests) 871ms
 Test Files  2 passed (2)
      Tests  4 passed (4)

2. My own drive, not the spec. A bash script over obsidian:e2e eval and CDP input. Two Capture choices that write Person: {{VALUE:Name}} to the active note, one with onePageInput always and one with never, loaded from data.json. Flow: open a fresh note, run the choice command, real click on Peek at note, open an Obsidian Modal titled New Event with a 60vh textarea, real click on Return in the chip.

At the landing tree, in both modes:

  • After Return, document.elementFromPoint at the focused field's centre is the field. Body order of modal containers is New Event, then the QuickAdd prompt.
  • The returned prompt's Peek button is not rendered while New Event is open: zero client rects, computed display none.
  • Ctrl+Shift+E over CDP does not peek again: the prompt stays visible, no chip appears, and the field is still on top.
  • Typing Ada and submitting (Ctrl+Enter for the form, Enter for the single prompt) writes Person: Ada\n# Event\n to the note. New Event is still open afterwards and closes cleanly.
  • A plain peek and Return with no other modal keeps the field value half written and the caret at 4, focus on the field, the field on top, and the Peek button visible. As a control, Ctrl+Shift+E peeks there and a second Ctrl+Shift+E returns, with value and caret intact.
  • dev:errors reports no errors.

The same script at 0ed8d456~1 fails only the stacking checks, in both modes: field on top after Return: got covered by New Event and body order QuickAdd prompt, then New Event. The hidden Peek button and the inert chord over the other modal behave the same at the parent, so they come from #2239 and this PR changes only the stacking.

3. Checks at the landing tree. pnpm run test: 501 files passed, 6 skipped; 6883 tests passed, 28 skipped. pnpm run lint: clean (oxlint, svelte-policy 0 errors 0 warnings, tsconfig check, svelte-check 58 files 0 errors 0 warnings).

The known accepted gaps (Android Back after Return, Ctrl/Cmd+Shift+E returning to a peeked prompt while another plugin's modal is open) were not exercised. Nothing worse was seen. The Obsidian instance is stopped.

@chhoumann
chhoumann merged commit 283f0d2 into master Oct 13, 2026
18 checks passed
@chhoumann chhoumann mentioned this pull request Oct 13, 2026
@chhoumann
chhoumann deleted the issue-2235 branch October 13, 2026 21:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG]

1 participant