Skip to content

Suggestion menus: whitespace-boundary anchoring and no blank renders - #85

Open
janglad wants to merge 1 commit into
mainfrom
fix/web-4236-email-input-studio-addresses-are-not-accepted-correctly
Open

janglad wants to merge 1 commit into
mainfrom
fix/web-4236-email-input-studio-addresses-are-not-accepted-correctly

Conversation

@janglad

@janglad janglad commented Oct 5, 2026 •

Copy link
Copy Markdown
Member

What changed

  • resolveSuggestionMenuTarget: with boundary: "whitespace", the match now anchors on the last trigger that has whitespace (or the start of the lookbehind) before it, instead of rejecting when the last trigger character does not. A later trigger character is part of the query, so @ada@example resolves as one query rather than closing the menu at the second @. boundary: "any" is unchanged.
  • useSuggestionMenu:
    • A synchronous getItems result is applied in the same state update as the new target, with no intermediate loading render.
    • For an async getItems, a query refined on the same trigger keeps the previous items while status is loading. Stale responses are still dropped.
    • A getItems that throws synchronously now resolves to the error state instead of escaping the refresh.
  • @input/pen-types: new isPromiseLike guard, used by the hook and by core's extension lifecycle in place of two inline thenable checks.

Why

A host that renders the menu only while it has items saw it close and reopen on every keystroke, and a whitespace-bounded trigger could not be used for queries that contain the trigger character, such as email addresses.

Breaking

Yes, for hosts using boundary: "whitespace" that relied on a second trigger character closing the menu (for example :smile:). Set closingChar to keep that behaviour.

Specs and changesets

  • spec/rules/selection.md (N6) and spec/packages/rendering/react.md amended.
  • Two changesets: @input/pen-core minor (breaking), and @input/pen-react / @input/pen-core / @input/pen-types patch.

Testing

  • New cases in resolveSuggestionMenuTarget.n6.test.ts for the anchoring and the no-valid-trigger case.
  • New cases in suggestionMenu.staleResults.test.tsx for the synchronous path, retained items during loading, and the synchronous throw.

Note

Medium Risk
Breaking change to whitespace-boundary trigger resolution affects mention/emoji hosts; menu refresh logic changes observable loading/error behavior in React suggestion UIs.

Overview
Suggestion menus get steadier UX and more predictable trigger matching.

resolveSuggestionMenuTarget with boundary: "whitespace" now anchors on the last @ (or trigger) that has whitespace or lookbehind start before it, so text like @ada@example is one query instead of reopening at the second trigger. Hosts that depended on a second trigger character to close the menu (e.g. :smile:) should set closingChar. boundary: "any" is unchanged.

useSuggestionMenu avoids blanking the list on each keystroke: synchronous getItems applies items in the same update (no flash of empty loading); async refreshes on the same trigger keep prior items while loading; synchronous throws surface as error. isPromiseLike is exported from @input/pen-types and shared by the hook and extension activate/deactivate lifecycle.

Reviewed by Cursor Bugbot for commit cc0b350. Bugbot is set up for automated code reviews on this repo. Configure here.

…oundary handling

- Updated `useSuggestionMenu` to apply synchronous `getItems` results without rendering an empty loading state, improving user experience during typing.
- Enhanced `resolveSuggestionMenuTarget` to anchor on the last whitespace-triggered character, allowing for more intuitive query handling.
- Introduced tests to validate the new behavior for both synchronous and asynchronous item fetching, ensuring stability and correctness.

No breaking changes introduced.
@janglad

janglad commented Oct 5, 2026

Copy link
Copy Markdown
Member Author

bugbot run

@cursor cursor Bot 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 cc0b350. Configure here.

This branch has not been deployed

No deployments
Sign up for free to 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