Skip to content

feat(EditorSuggestionMenu): expose TipTap suggestion matching options#6234

Open
Archetipo95 wants to merge 3 commits intonuxt:v4from
Archetipo95:feat/editor-suggestion-menu-suggestion-options
Open

feat(EditorSuggestionMenu): expose TipTap suggestion matching options#6234
Archetipo95 wants to merge 3 commits intonuxt:v4from
Archetipo95:feat/editor-suggestion-menu-suggestion-options

Conversation

@Archetipo95
Copy link

🔗 Linked issue

Resolves #6233

❓ Type of change

  • 📖 Documentation (updates to the documentation or readme)
  • 🐞 Bug fix (a non-breaking change that fixes an issue)
  • 👌 Enhancement (improving an existing functionality)
  • ✨ New feature (a non-breaking change that adds functionality)
  • 🧹 Chore (updates to the build process or auxiliary tools and libraries)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)

📚 Description

This PR exposes TipTap suggestion matching options on UEditorSuggestionMenu so users can customize how trigger characters are matched.

The main change is adding a new optional suggestion?: Partial<SuggestionOptions> prop to UEditorSuggestionMenu and threading it through EditorMenuOptions into the internal TipTap Suggestion(...) configuration.

This allows opt-in use cases such as setting allowedPrefixes: null so a : trigger can open directly after / or letters, instead of only after whitespace.

The implementation preserves existing behavior.

This PR also includes:

  • unit tests for forwarded suggestion options
  • regression coverage for default behavior when suggestion is omitted
  • documentation for the new prop on the EditorSuggestionMenu page
  • a changelog entry

📝 Checklist

  • I have linked an issue or discussion.
  • I have updated the documentation accordingly.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 24, 2026

📝 Walkthrough

Walkthrough

This PR adds support for exposing TipTap suggestion matching options through a new optional suggestion prop on the EditorSuggestionMenu component. The implementation allows users to customize trigger matching behavior (e.g., allowedPrefixes, allowSpaces, startOfLine) by passing a Partial<SuggestionOptions> object. Changes include updating the component to accept and forward the suggestion configuration, modifying the useEditorMenu composable to merge suggestion options into the TipTap plugin setup, documenting the feature with usage examples, adding comprehensive test coverage, and recording the changes in the changelog.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: exposing TipTap suggestion matching options on EditorSuggestionMenu.
Description check ✅ Passed The description comprehensively explains the changes, including the motivation, implementation approach, and what's included (tests, docs, changelog).
Linked Issues check ✅ Passed The PR fully addresses issue #6233 by implementing Option A: adding the suggestion?: Partial prop to expose TipTap matching options while preserving existing defaults.
Out of Scope Changes check ✅ Passed All changes are in-scope: component props, composable options, tests, documentation, and changelog entry all directly support exposing the suggestion matching options.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/runtime/composables/useEditorMenu.ts`:
- Around line 68-71: The suggestion spread currently allows options.suggestion
to override core fields (pluginKey, editor, char) which can break plugin state;
update the construction around options.suggestion (where suggestion?:
Partial<SuggestionOptions> is used and options.suggestion is spread) so that
pluginKey, editor and char are applied after spreading user options OR
explicitly omit those keys from the spread (i.e., create a sanitizedSuggestion =
{ ...options.suggestion } without pluginKey/editor/char) and then build the
final suggestion object using pluginKeyInstance/pluginKey/editor/char last to
ensure the core values always take precedence.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 709ec4e6-dd63-4a8c-bfb2-910d23119493

📥 Commits

Reviewing files that changed from the base of the PR and between 90a94fb and 5537ad8.

📒 Files selected for processing (5)
  • CHANGELOG.md
  • docs/content/docs/2.components/editor-suggestion-menu.md
  • src/runtime/components/EditorSuggestionMenu.vue
  • src/runtime/composables/useEditorMenu.ts
  • test/composables/useEditorMenu.spec.ts

Comment on lines +68 to +71
/**
* Optional TipTap Suggestion matching options.
*/
suggestion?: Partial<SuggestionOptions>
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

In the current @tiptap/suggestiontype/docs, doesSuggestionOptionsincludepluginKey, editor, and char, and are they intended to be externally overridden in wrapper APIs?

💡 Result:

No, in the current @tiptap/suggestion (v3.x as of 2026), the SuggestionOptions interface does not include pluginKey, editor, or char as configurable properties in the way typically used when configuring extensions via .configure. Instead, these are direct parameters to the standalone Suggestion function that returns a ProseMirror plugin. The official Tiptap documentation lists char, pluginKey, allow, shouldShow, etc., as "Settings" for the Suggestion utility, with examples like Suggestion({ char: '@', pluginKey: SuggestionPluginKey, ... }). This matches the source code signature: export function Suggestion({ pluginKey = SuggestionPluginKey, editor, // required char = '@', ... }: SuggestionOptions) editor is required when calling Suggestion directly (internal use by extensions like Mention), but omitted in extension .configure calls (e.g., suggestion: { char: '#', command: ... } uses Omit<SuggestionOptions, 'editor'>). They are not intended for external override in wrapper APIs like node extensions. Wrapper extensions (Mention, Hashtag) expose a suggestion prop that accepts a subset excluding editor, with pluginKey often hardcoded (e.g., MentionPluginKey), and char customizable. Users override via the extension's suggestion config, not raw SuggestionOptions.

Citations:


🏁 Script executed:

# First, check if the file exists and get its line count
wc -l src/runtime/composables/useEditorMenu.ts

Repository: nuxt/ui

Length of output: 95


🏁 Script executed:

# View the import section and the type definition around lines 68-71
head -n 90 src/runtime/composables/useEditorMenu.ts | tail -n +1

Repository: nuxt/ui

Length of output: 3011


🏁 Script executed:

# View the Suggestion plugin config section around lines 496-501
sed -n '490,510p' src/runtime/composables/useEditorMenu.ts

Repository: nuxt/ui

Length of output: 607


Prevent suggestion from overriding core plugin wiring (pluginKey/editor/char).

At lines 496–501, the spread of options.suggestion occurs after the core fields are defined, allowing pluginKey, editor, and char to be overridden. If pluginKey is overridden, your exit transaction (which uses pluginKeyInstance) can target a different plugin key and leave sessions in a bad state.

Constrain the suggestion option to exclude these fields and ensure they always take precedence by reordering the spread:

🔧 Proposed fix
+type EditorMenuSuggestionOptions = Omit<
+  Partial<SuggestionOptions>,
+  'pluginKey' | 'editor' | 'char' | 'items' | 'command' | 'render'
+>
+
 export interface EditorMenuOptions<T = any> {
   editor: Editor
   /**
    * The trigger character (e.g., '/', '@', ':')
    */
   char: string
   /**
    * Plugin key to identify this menu
    */
   pluginKey: string
   ...
-  suggestion?: Partial<SuggestionOptions>
+  suggestion?: EditorMenuSuggestionOptions
   const plugin = Suggestion({
-    pluginKey: pluginKeyInstance,
-    editor: options.editor,
-    char: options.char,
     ...(options.suggestion || {}),
+    pluginKey: pluginKeyInstance,
+    editor: options.editor,
+    char: options.char,
     items: ({ query: q }: { query: string }) => {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/runtime/composables/useEditorMenu.ts` around lines 68 - 71, The
suggestion spread currently allows options.suggestion to override core fields
(pluginKey, editor, char) which can break plugin state; update the construction
around options.suggestion (where suggestion?: Partial<SuggestionOptions> is used
and options.suggestion is spread) so that pluginKey, editor and char are applied
after spreading user options OR explicitly omit those keys from the spread
(i.e., create a sanitizedSuggestion = { ...options.suggestion } without
pluginKey/editor/char) and then build the final suggestion object using
pluginKeyInstance/pluginKey/editor/char last to ensure the core values always
take precedence.

@pkg-pr-new
Copy link

pkg-pr-new bot commented Mar 24, 2026

npm i https://pkg.pr.new/@nuxt/ui@6234

commit: 5537ad8

Copy link
Contributor

@howwohmm howwohmm left a comment

Choose a reason for hiding this comment

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

nice addition — exposing TipTap's suggestion matching options is useful for custom slash commands.

one thing worth watching: the spread order in the suggestion config means options.suggestion could accidentally override pluginKey or editor since it's spread after those positional keys. a consumer passing suggestion: { pluginKey: ... } would silently replace the internal plugin key.

safest fix would be to destructure and omit the dangerous keys before spreading:

const { pluginKey: _pk, editor: _ed, char: _ch, ...safeSuggestion } = options.suggestion || {}

or move pluginKey, editor, and char after the spread so they always win. either way it's a one-line guard against a subtle footgun.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v4 #4488

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expose TipTap suggestion matching options in UEditorSuggestionMenu (allowedPrefixes, startOfLine, etc.)

2 participants