Repository navigation
Ctrl+P Closes Search Palette Instead of Navigating Up #938
Description
- Type: Bug
- Severity: Medium
Environment
- OS: Linux
- WM: Niri
- Compositor: Wayland
- Software version: 2.69.0
Description
In the Search Notes palette, Ctrl+P is documented as an alternative to ArrowUp for moving the selection to the previous result. It instead closes the palette.
The same chord closes the palette from inside the New note form that the palette's create row opens. That form holds the typed name, folder, and tags in component state, so pressing Ctrl+P while filling it in discards everything that was typed.
The palette's own footer advertises this chord, reading ↑↓ Ctrl+N/P move, so the interface promises exactly the behaviour that does not happen.
This is not a preference local to Search Notes. Ctrl+P moving the selection up is an established convention backed by one shared helper. Open Notes (Space+O) is the clearest case: the same chord moves the selection up there, which is exactly the behaviour missing here. Command Palette, Templates (New from Template, Insert Template into Note), Search text in vault and Settings search share it too. Search Notes is the only palette that closes instead, and it does so only because of a collision with its own opening shortcut.
One surface imports the same helper without navigating on it, and it is worth naming so the convention is not over-read. Quick capture does not, but for an unrelated reason: it renders as its own window root rather than the main app, so it has no list driven by this helper. Its Ctrl+P toggles that window's own note picker, which is separate behaviour and not part of this defect.
Ctrl+N, Ctrl+J and Ctrl+K navigate correctly wherever there is a list to move through: the result list, and the folder and tag lists of the New note form. None of the four does anything in the form's Name field, which has no list to move through. That is correct, and it is a separate matter. Among the surfaces that do have a list, Ctrl+P alone is affected.
Steps to Reproduce
- Open the Search Notes palette with
Ctrl+P. - Type a query that returns more than one result.
- Press
Ctrl+P. - Observe that the palette closes instead of the selection moving up.
On the second surface:
- Open the Search Notes palette with
Ctrl+P. - Type a query that matches no existing note.
- Move to the create row and press
Enterto open the New note form. - Type a name and a partial folder path.
- Press
Ctrl+P. - Observe that the palette closes and the typed name and folder are gone.
Expected Behaviour
Ctrl+P should move the selection to the previous item, as ArrowUp does, and leave the palette open.
From inside the New note form it should move the selection within the folder or tag list under the focused field, and leave the form open with its contents intact.
Actual Behaviour
Ctrl+P closes the entire Search Notes palette in every case. Typed input in the New note form is lost.
Why Ctrl+P Never Reaches the Palette
Palettes accept three flavours of "move selection": the arrow keys, the Emacs pair Ctrl+N / Ctrl+P, and the vim pair Ctrl+J / Ctrl+K. Ctrl+P is recognised by isPalettePreviousKey() in packages/app-core/src/lib/palette-nav.ts, and SearchPalette consumes it to move up.
It is intercepted before it can get there. The shortcut that opens and toggles Search Notes is Mod+P, which resolves to Ctrl+P on Linux and Windows and Cmd+P on macOS. The toggle is handled by focusPaneHandler in packages/app-core/src/App.tsx, which is registered on window in the capture phase.
Its first job is to close the palette when its own shortcut is pressed again, and it does so by calling both preventDefault() and stopImmediatePropagation().
A capture-phase listener on window runs before the event reaches React's delegated root listener, and stopImmediatePropagation() stops it entirely. The palette's own key handler therefore never observes the event, and the Ctrl+P branch of isPalettePreviousKey() is unreachable for as long as the palette is open.
Winning over Vim's Ctrl+P (cursor up) on Linux and Windows is intentional, and is the reason the handler sits in the capture phase. The defect is that the toggle claims the chord unconditionally, without yielding to a palette that is already open and already consumes it.
Ctrl+N, Ctrl+J and Ctrl+K have no global binding, so they pass through the capture handler untouched and navigate as intended.
Affected Surfaces
- The Search Notes result list, where
Ctrl+Pcloses the palette. - The New note form's folder and tag lists, where
Ctrl+Pcloses the palette and discards typed input.
The toggle consults a set of modal selectors before acting, which is how the Ctrl+D trash confirmation keeps Ctrl+P to itself. The New note form carries data-search-create-form, which is not in that set, so the toggle does not treat it as a modal and does not defer to it.
Suggested Behaviour
Make Ctrl+P mean one thing at a time: it opens the palette when the palette is closed, and navigates the selection when it is open.
Removing the toggle-close is preferable to making it yield to the palette. The toggle is the sole cause of the collision, so deleting it fixes this bug and removes the whole class, any future global binding that overlaps one of the palette-nav chords becomes safe by default, rather than needing to be special-cased. A guard would only ever patch the one instance that exists today.
The end state is the one the rest of the app already has: Ctrl+P navigates the selection up while a palette holds focus, and opens Search Notes when no palette is open.
The other palette surfaces must not change. Ctrl+P has to keep moving the selection up in Open Notes and the eleven other consumers of the shared helper. They are unaffected today, because the toggle only fires while Search Notes is open, and they stay unaffected afterwards, the overlay guard that stops a global shortcut from firing over an open palette already covers them. This is the constraint a narrower fix could plausibly break, so it belongs in the verification.
Nothing is lost by dropping it:
escis the documented dismiss key, and the palette footer already says so.- The app's own reference material describes
Mod+Pas opening the palette. Neither the keymap description nor the in-app manual claims it toggles, so removing the toggle aligns the code with the documented contract rather than the other way round. - Opening a note and clicking outside both dismiss the palette already.
The cost is losing press-again-to-dismiss, which every other Ctrl+P palette trains users to expect. A user pressing Ctrl+P a second time expecting dismissal will move the selection up instead. That is a small, learnable surprise, and it is the same chord the footer tells them moves.
Additional Notes
ArrowUpstill works everywhereCtrl+Pis documented, so there is a workaround.- The interception happens before the field's own handler runs, so it cannot be resolved inside the palette or the form component. The toggle in
App.tsxis the thing that has to go. - The toggle was introduced deliberately in Global Shortcuts should trample Vim Mode shortcuts consistently or in an explainable way. #510, which moved it into the capture-phase handler so it would run ahead of the editor. Opening the palette is a separate path in the same handler and is unaffected by removing the toggle, so Global Shortcuts should trample Vim Mode shortcuts consistently or in an explainable way. #510's original problem stays fixed.
- The
Ctrl+Dtrash confirmation needs no replacement protection. It was guarded by the toggle declining to fire while a modal was open; with the toggle gone,Ctrl+Pno longer dismisses the palette at all.
Activity
uNyanda commentedon Oct 13, 2026
Fixed in #939
adibhanna commentedon Oct 13, 2026
Thanks @uNyanda, a precise report. Confirmed on
main: the Search Notes toggle infocusPaneHandler(App.tsx) runs in the capture phase and stops the event, so on Linux and Windows, whereMod+PisCtrl+P, the palette never sees the key it uses to move up, in the result list or in the New note form. Closing this in favor of your #939, which carries the fix and will be reviewed for the next release.Chore(search): the Search Notes comment names #938, the issue it fixes
Fix(keys): global shortcuts wait for every dialog, not just marked on…