Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/slash-menu-click-outside.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@moonshot-ai/kimi-web': patch
---

Close slash and mention menus when clicking outside the composer.
35 changes: 34 additions & 1 deletion apps/kimi-web/src/components/chat/Composer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,38 @@ const {
searchFiles: () => props.searchFiles,
});

// ---------------------------------------------------------------------------
// Close slash/mention menus on click outside
// ---------------------------------------------------------------------------

const cinWrapRef = ref<HTMLDivElement | null>(null);

function closeMenus(): void {
slashOpen.value = false;
mentionOpen.value = false;
// Cancel any pending mention lookup so the menu does not re-open after an
// outside click while the debounced search is still in flight.
if (mentionTimer !== null) {
clearTimeout(mentionTimer);
mentionTimer = null;
}
mentionLoading.value = false;
}

function onComposerDocClick(e: MouseEvent): void {
const t = e.target as Node;
if (cinWrapRef.value?.contains(t)) return;
closeMenus();
}

watch(() => slashOpen.value || mentionOpen.value, (open) => {
if (open) {
document.addEventListener('click', onComposerDocClick, true);
Comment on lines +160 to +162

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Cancel pending mention lookups on outside clicks

When a user types @ and clicks the chat area before the 200 ms mention debounce fires, mentionOpen is still false, so this watcher has not installed the document click listener yet. The pending mentionTimer callback can then run after the composer has lost focus and set mentionOpen = true, leaving the mention menu open even though the user already clicked outside; the outside-close path needs to cancel pending mention work or listen while a mention search is pending.

Useful? React with 👍 / 👎.

} else {
document.removeEventListener('click', onComposerDocClick, true);
}
});

// ---------------------------------------------------------------------------
// Input event handler — updates both menus
// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -452,6 +484,7 @@ function onDocClick(e: MouseEvent): void {

onUnmounted(() => {
document.removeEventListener('click', onDocClick, true);
document.removeEventListener('click', onComposerDocClick, true);
});

// Context formatting
Expand Down Expand Up @@ -637,7 +670,7 @@ function selectModel(modelId: string): void {
<!-- Main composer card -->
<div class="composer-card">
<!-- Input row with popup menus -->
<div class="cin-wrap">
<div ref="cinWrapRef" class="cin-wrap">
<!-- Slash menu (above textarea) -->
<SlashMenu
v-if="slashOpen"
Expand Down