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') {