Skip to content

fix(user-input): stop @mention/skill menu from reopening after dismiss - #5464

Merged
waleedlatif1 merged 3 commits into
stagingfrom
fix-mention-menu-click-away
Jul 7, 2026
Merged

fix(user-input): stop @mention/skill menu from reopening after dismiss#5464
waleedlatif1 merged 3 commits into
stagingfrom
fix-mention-menu-click-away

Conversation

@waleedlatif1

Copy link
Copy Markdown
Collaborator

Summary

  • Fixes a bug where the @mention (and /skill) autocomplete menu couldn't be dismissed — clicking away or pressing Escape closed it, but the very next click/selection change reopened it because the caret was still inside the unfinished @token
  • Adds a one-shot "dismissed" marker per token, set only on a real outside-click/Escape dismiss, cleared the instant the user types again
  • Shared fix in use-prompt-editor.ts covers every consumer: home chat input, scheduled-task modal, task-details modal

Type of Change

  • Bug fix

Testing

Added use-prompt-editor.test.tsx (4 tests) that mounts the real hook and reproduces the exact scenario — confirmed it fails on the pre-fix code and passes after. Also ran full typecheck/lint.

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

- Fixes a bug where the @mention (and /skill) autocomplete menu couldn't
be dismissed: clicking away or pressing Escape closed it, but the very
next click/selection change reopened it because the caret was still
inside the unfinished @token
- Adds a one-shot "dismissed" marker per token, set only on a real
outside-click/Escape dismiss, cleared the instant the user types again
- Shared fix in use-prompt-editor.ts covers every consumer: home chat
input, scheduled-task modal, task-details modal
@vercel

vercelBot commented Jul 7, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
ProjectDeploymentActionsUpdated (UTC)
docsSkippedSkippedJul 7, 2026 3:21am

Request Review

@cursor

cursorBot commented Jul 7, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Localized prompt-editor UX logic with new regression tests; no API, auth, or data-path changes.

Overview
Fixes @mention and /skill autocomplete menus popping back open right after the user dismisses them (outside click or Escape) when the caret is still inside the unfinished @ or / token.

use-prompt-editor now records a one-shot dismissed token start on Radix-driven closes (handlePlusMenuClose / handleSkillsMenuClose) and syncMentionState / syncSlashState skip reopening for that exact token on the next selection sync. Typing, clearing, picks, and toolbar slash insert clear the marker so continued typing or a new mention still opens the menu.

Adds use-prompt-editor.test.tsx with jsdom hook tests for dismiss-without-reopen, reopen after more typing, a different @ mention, and slash toolbar after dismiss.

Reviewed by Cursor Bugbot for commit 5e55525. Configure here.

@greptile-apps

greptile-appsBot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR fixes a menu-persistence bug in the prompt editor where dismissing an @mention or /skill autocomplete menu (via outside-click or Escape) caused it to reopen immediately because the caret remained inside the unfinished token, triggering syncMentionState/syncSlashState on the next selection-change event.

  • Adds two one-shot refs (dismissedMentionStartRef, dismissedSlashStartRef) that record the token's start offset when the user explicitly dismisses the menu, and suppress the reopen in syncMentionState/syncSlashState until the user types again or the token becomes invalid.
  • Clears the dismissed refs consistently in all "typing resumed" paths: handleInputChange, insertSlashTrigger, and the word-boundary !isOpenable branch of both sync functions.
  • Adds four focused unit tests that mount the real hook against a jsdom textarea and cover the core dismiss, reopen-on-keystroke, and new-token scenarios.

Confidence Score: 5/5

Safe to merge — the change is isolated to two ref variables in one hook, all existing reset paths are updated, and the fix is verified by new tests.

The dismissed-position refs are read-only inside syncMentionState/syncSlashState and written only in the dismiss handlers and typing-resumed paths. Every code path that previously nulled mentionRangeRef/slashRangeRef now also nulls the new dismissed refs, so there is no stale-suppression risk. Position-based identity correctly identifies the same token across selection-change events, and any in-place text mutation goes through handleInputChange which clears the refs immediately.

No files require special attention.

Important Files Changed

FilenameOverview
apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/prompt-editor/use-prompt-editor.tsAdds two one-shot dismissed-position refs that suppress syncMentionState/syncSlashState from reopening a menu on selection-change after an explicit user dismissal; refs are cleared on any subsequent keystroke or token-boundary change, and in all existing reset paths.
apps/sim/app/workspace/[workspaceId]/home/components/user-input/components/prompt-editor/use-prompt-editor.test.tsxNew test file mounting the real hook in a jsdom root; covers four behavioral scenarios for mention-menu dismissal and one for the toolbar slash trigger, following the established test pattern in the codebase.

Sequence Diagram

%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant User
participant Textarea
participant handleInputChange
participant handlePlusMenuClose
participant handleSelectAdjust
participant syncMentionState
participant PlusMenu
User->>Textarea: "types "@f""
Textarea->>handleInputChange: input event
handleInputChange->>syncMentionState: clears dismissed ref, then syncs
syncMentionState->>PlusMenu: open()
User->>handlePlusMenuClose: Escape / outside click
handlePlusMenuClose->>handlePlusMenuClose: "dismissedMentionStartRef = 0"
handlePlusMenuClose->>handlePlusMenuClose: "mentionRangeRef = null"
User->>Textarea: "clicks back into token (caret=2)"
Textarea->>handleSelectAdjust: selectionchange
handleSelectAdjust->>syncMentionState: "active.start(0) === dismissed(0) SUPPRESS"
syncMentionState-->>PlusMenu: not reopened
User->>Textarea: types more
Textarea->>handleInputChange: "clears dismissedMentionStartRef = null"
handleInputChange->>syncMentionState: suppression lifted
syncMentionState->>PlusMenu: open()
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant User
participant Textarea
participant handleInputChange
participant handlePlusMenuClose
participant handleSelectAdjust
participant syncMentionState
participant PlusMenu
User->>Textarea: "types "@f""
Textarea->>handleInputChange: input event
handleInputChange->>syncMentionState: clears dismissed ref, then syncs
syncMentionState->>PlusMenu: open()
User->>handlePlusMenuClose: Escape / outside click
handlePlusMenuClose->>handlePlusMenuClose: "dismissedMentionStartRef = 0"
handlePlusMenuClose->>handlePlusMenuClose: "mentionRangeRef = null"
User->>Textarea: "clicks back into token (caret=2)"
Textarea->>handleSelectAdjust: selectionchange
handleSelectAdjust->>syncMentionState: "active.start(0) === dismissed(0) SUPPRESS"
syncMentionState-->>PlusMenu: not reopened
User->>Textarea: types more
Textarea->>handleInputChange: "clears dismissedMentionStartRef = null"
handleInputChange->>syncMentionState: suppression lifted
syncMentionState->>PlusMenu: open()
Loading

Reviews (3): Last reviewed commit: "fix(user-input): clear slash dismissal m..." | Re-trigger Greptile

…smiss fix
Trims the inline // explanations added in the previous commit down to
the two declaration-level doc comments that carry real information —
matching the repo's no-inline-comments convention.
…gger
Cursor Bugbot review: insertSlashTrigger (the toolbar Slash button) called
syncSlashState without clearing dismissedSlashStartRef, so a stale dismissal
could suppress the skills menu on an explicit user action when the new
token's start offset coincided with the previously dismissed one. An
explicit trigger click must always open the menu, so it now clears the
marker first like every other insertion path.
@waleedlatif1
waleedlatif1 merged commit cad44b9 into stagingJul 7, 2026
4 checks passed
@waleedlatif1
waleedlatif1 deleted the fix-mention-menu-click-away branch July 7, 2026 03:22
@waleedlatif1

Copy link
Copy Markdown
CollaboratorAuthor

@greptile

@waleedlatif1

Copy link
Copy Markdown
CollaboratorAuthor

@cursor review

@waleedlatif1

Copy link
Copy Markdown
CollaboratorAuthor

@greptile

@waleedlatif1

Copy link
Copy Markdown
CollaboratorAuthor

@cursor review

@cursorcursorBot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 5e55525. Configure here.

Sign up for freeto 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.

1 participant

@waleedlatif1