From c1d43b9b18ffabcc75d9083c406af7c4e8018e66 Mon Sep 17 00:00:00 2001 From: likljn Date: Wed, 7 Jan 2026 11:13:13 +0900 Subject: [PATCH] fix(editor): keep slash menu alive on text input when no_result (#14141) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit **Problem** Slash menu can be prematurely aborted when the query is still in `no_result` due to async query updates after deletion. **Solution** Keep the slash menu alive on text input while in `no_result`, preventing aborts based on a stale query state. **Repro** 1. Type `/eeee` 2. Delete to `/` 3. Type `h` 4. Slash menu should recover and show results ## Summary by CodeRabbit * **Bug Fixes** * Enhanced slash-menu keyboard interaction: users can now continue typing to refine queries when no results are displayed, instead of the menu closing unexpectedly. Keyboard navigation and other controls remain responsive. ✏️ Tip: You can customize this high-level summary in your review settings. Co-authored-by: DarkSky <25152247+darkskygit@users.noreply.github.com> --- .../slash-menu/src/slash-menu-popover.ts | 26 ++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/blocksuite/affine/widgets/slash-menu/src/slash-menu-popover.ts b/blocksuite/affine/widgets/slash-menu/src/slash-menu-popover.ts index 9c473eef9..2d6f31cdd 100644 --- a/blocksuite/affine/widgets/slash-menu/src/slash-menu-popover.ts +++ b/blocksuite/affine/widgets/slash-menu/src/slash-menu-popover.ts @@ -46,6 +46,22 @@ import { parseGroup, slashItemClassName, } from './utils.js'; +const isTextInputKey = (e: KeyboardEvent) => { + // Keys combined with modifiers are not considered text input + if (e.ctrlKey || e.metaKey || e.altKey) return false; + + // During IME composition, do not treat keydown as text input. + // Query updates are handled by input/composition hooks. + if (e.isComposing) return false; + + // Only allow single-character keys as text input + if (e.key.length !== 1) return false; + + // Keep existing behavior: space closes the slash menu + if (e.key === ' ') return false; + + return true; +}; type InnerSlashMenuContext = SlashMenuContext & { onClickItem: (item: SlashMenuActionItem) => void; searching: boolean; @@ -228,10 +244,12 @@ export class SlashMenu extends WithDisposable(LitElement) { } if (key !== 'Backspace' && this._queryState === 'no_result') { - // if the following key is not the backspace key, - // the slash menu will be closed - this.abortController.abort(); - return; + if (isTextInputKey(event)) { + // allow typing to change query; don't abort here + } else { + this.abortController.abort(); + return; + } } if (key === 'Escape') {