Skip to content

fix(InputMenu/SelectMenu): prevent unintended item creation and improve focus handling#5986

Open
lorado wants to merge 12 commits intonuxt:v4from
lorado:v4
Open

fix(InputMenu/SelectMenu): prevent unintended item creation and improve focus handling#5986
lorado wants to merge 12 commits intonuxt:v4from
lorado:v4

Conversation

@lorado
Copy link
Copy Markdown

@lorado lorado commented Feb 3, 2026

🔗 Linked issue

Resolves #5974

❓ 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

Based on the issues described in #5974, following fixes were applied:

  • InputMenu
    • Stop propagation of the "Enter"-key event on the TagsInputInput preventing calling default Reka behaviour, which triggers an internal onAddValue, which isn't connected in any way to Nuxt UI
    • Watch changes in items prop, and in filters are ignored and creation is enabled, trigger to select first item in the dropdown.
  • SelectMenu
    • Similar to InputMenu, SelectMenu had similar issue with focus in Combobox
  • Added additional examples of usage to playground, which covers issues which are fixed now.

📝 Checklist

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

I don't think there is a need to write anything to documentation?

@lorado lorado requested a review from benjamincanac as a code owner February 3, 2026 14:47
@github-actions github-actions Bot added the v4 #4488 label Feb 3, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 3, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds combobox root refs and a post-flush watcher in InputMenu.vue and SelectMenu.vue to call highlightFirstItem() when props.items change while the dropdown is open, ignoreFilter is true, and a createItem exists. Introduces isDropdownOpened state, binds comboboxRootRef, and adds an onInputEnter handler wired to Enter key events to manage create-vs-select behavior. Playground pages (input-menu.vue and select-menu.vue) add parallel "create" flows: searchTermCreate and debounced variants, lazy useFetch calls producing usersCreate with avatar transforms, statusCreate loading flags, and onUserCreate handlers; templates include create-enabled multiple selection inputs/selects.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main changes: fixing unintended item creation and improving focus handling in InputMenu and SelectMenu components.
Description check ✅ Passed The description clearly relates to the changeset, referencing issue #5974 and explaining the fixes applied to InputMenu and SelectMenu with specific technical details.
Linked Issues check ✅ Passed The PR addresses both problems from #5974: (1) tracking dropdown state and highlighting first item when items change; (2) preventing unintended onCreate by stopping Enter key propagation on TagsInputInput and properly handling focus transitions.
Out of Scope Changes check ✅ Passed All changes in InputMenu.vue, SelectMenu.vue and playground files are directly scoped to fixing focus handling and preventing unintended creation as specified in issue #5974.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ 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.

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Feb 3, 2026

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

commit: 527f77f

Copy link
Copy Markdown
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

🤖 Fix all issues with AI agents
In `@src/runtime/components/SelectMenu.vue`:
- Around line 487-492: The onInputEnter handler currently calls onCreate(e)
whenever there is no highlighted element regardless of whether creation is
enabled; update onInputEnter to first check props.createItem (or an equivalent
create-enabled flag) and only call onCreate(e) when props.createItem is truthy
and comboboxRootRef.value?.highlightedElement is falsy, so pressing Enter won’t
emit a create event when create is disabled; refer to the onInputEnter function,
the onCreate handler, and props.createItem to implement this guard.

Comment thread src/runtime/components/SelectMenu.vue
@lorado
Copy link
Copy Markdown
Author

lorado commented Feb 3, 2026

Just realised there was still a not intuitive situation, when focus was in the input-tag, and user moved the focus out of the CheckboxItem, added last failsafe so that on "Enter"-key hit onCreate function still called, but only if there are no items available. If there are any items available, but focus is out of the combobox, I decided to simply bring the focus back to the first option available.

Let me know if there is any need for change.

Copy link
Copy Markdown
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

🤖 Fix all issues with AI agents
In `@src/runtime/components/InputMenu.vue`:
- Around line 503-516: The onInputEnter function currently calls onCreate
unconditionally when there are no items; update it to guard against unwanted
creation by checking the creation flag (e.g., props.createItem or whichever prop
enables creation) before invoking onCreate. In onInputEnter, after the existing
combobox focus and items checks, add a conditional that ensures props.createItem
is truthy (or the appropriate creation-enabled prop) and only then call
onCreate(e); otherwise do nothing (or return). This change should reference
onInputEnter, onCreate, comboboxRootRef, and props.items to locate and fix the
behavior.

Comment thread src/runtime/components/InputMenu.vue
@benjamincanac benjamincanac changed the title fix: bug in InputMenu and SelectMenu (#5974) fix(InputMenu/SelectMenu): prevent unintended item creation and improve focus handling Feb 6, 2026
@lorado
Copy link
Copy Markdown
Author

lorado commented Feb 11, 2026

Figured out, that props.items might be changing even if dropdown isn't displayed. In that case focus should not be triggered.
I added simple variable which is set on open state change, I am not sure if you prefer to use ref variable here.
Let me know if I have to change something

Copy link
Copy Markdown
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

🤖 Fix all issues with AI agents
In `@src/runtime/components/SelectMenu.vue`:
- Around line 489-506: The onInputEnter handler currently checks props.items to
decide whether to call comboboxRootRef.value?.highlightFirstItem?.(), which
prevents onCreate from being reached when client-side filtering leaves no
visible items; change that guard to use the rendered list length
(filteredItems.value.length) instead of props.items so Enter will create the
visible "create" option when there are no filtered matches; update the same
pattern in InputMenu.vue (the analogous handler) and keep the rest of the logic
(comboboxRootRef, createItem.value, onCreate) unchanged.

Comment thread src/runtime/components/SelectMenu.vue
Copy link
Copy Markdown
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.

read through the full diff — the fix direction is right but there's a functional issue in multiple mode.

the .stop.prevent modifier on the TagsInput enter handler (line ~167 in the diff) prevents default before onInputEnter runs. so even when comboboxRootRef.value?.highlightedElement exists and the handler returns early (intending to let reka-ui's native selection behavior through), the event has already been stopped and prevented. this means Enter-to-select a highlighted item won't work in multiple mode.

contrast with the single-mode input which has no .stop.prevent modifier on the template — it handles e.preventDefault() and e.stopPropagation() conditionally inside the function. the multiple-mode handler should do the same:

<!-- instead of -->
@keydown.enter.stop.prevent="onInputEnter"
<!-- use -->
@keydown.enter="onInputEnter"

and let the function call e.preventDefault() / e.stopPropagation() only when it actually handles the event (the createItem path).

also minor: if ((props.items && props.items.length > 0)) has unnecessary double parens — single parens match the rest of the codebase.

the watch on props.items with highlightFirstItem() for the ignoreFilter case is a good approach though.

# Conflicts:
#	src/runtime/components/InputMenu.vue
#	src/runtime/components/SelectMenu.vue
@lorado
Copy link
Copy Markdown
Author

lorado commented Mar 31, 2026

hi @howwohmm, thank you for your time!

I would like to disagree with you.

Enter event on hovered elements is processed before input, and RekaUI acutally kills these events in their logic. You can check it in ListboxRoot which is used in Combobox.

In case of multiple, TagsInputInput is used, which has its own logic for enter within RekaUI. This one was always ignored by NuxtUI, as value within component is managed within NuxtUI logic. So when RekaUI handler is getting executed, NuxtUI is not using it actually. If we would like to use it, then TagsInputRoot requires @add-tag=... handler, and we would need to provide/pass through convertValue, so that RekaUI logic can be processed properly. But this was ignored previously, thats why I simply decided to shut this processing completely down, to prevent unexpected results, which I actually faced.

Single case uses regular input, so there is no need to shut the event down.

I am updating code to keep this PR up to date, as I require this fix in my project.
Due recent additions of autocomplete, I need to check my changes again.

@lorado
Copy link
Copy Markdown
Author

lorado commented Mar 31, 2026

Ok, I merged to most recent v4 branch, adjusted code slightly (highlightedElement from RekaUI was always defined, but had to check isConnected now, I mean it was different earlier...), and applied fix from code rabbit suggestion

Everything seems to work. If you guys still need some changes - let me know

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.

InputMenu as autocomplete (dynamic options + create)

2 participants