feat(InputMenu): add autocomplete prop#6026
Conversation
commit: |
📝 WalkthroughWalkthroughAdds an Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). 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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/runtime/components/InputMenu.vue (1)
599-613:⚠️ Potential issue | 🟠 MajorDisable the
multiplestructural path whenautocompleteis enabled.Autocomplete mode is documented as free-form text, but template structure still enables tags/multiple rendering. That creates an incompatible mode mix.
🩹 Proposed fix
- :as-child="!!multiple" + :as-child="!!multiple && !autocomplete"- <TagsInputRoot - v-if="multiple" + <TagsInputRoot + v-if="multiple && !autocomplete"Also applies to: 638-649
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/runtime/components/InputMenu.vue` around lines 599 - 613, The template allows the multiple/tags structural path even when autocomplete mode is enabled, causing an incompatible mix; update the conditional rendering and related props to ensure the tags/multiple UI is disabled whenever autocomplete is true (e.g., change v-if="multiple" to v-if="multiple && !autocomplete" for TagsInputRoot and any other multiple-specific blocks, and adjust :as-child="!!multiple" to :as-child="multiple && !autocomplete" or equivalent), and apply the same change to the other occurrence referenced (lines ~638-649) so all multiple-specific markup is gated by multiple && !autocomplete.
🧹 Nitpick comments (1)
test/components/InputMenu.spec.ts (1)
167-179: Add regression tests for autocomplete-specific constraints.The new tests cover emits, but they don’t lock behavior for the high-risk cases introduced here (e.g., blur retention/defaults and interaction with
multiple). Adding those would prevent regressions in the new mode.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/components/InputMenu.spec.ts` around lines 167 - 179, Add regression tests to lock autocomplete-specific behaviors: extend the InputMenu spec by adding tests that (1) verify blur retention/defaults when autocomplete is true by mounting InputMenu with autocomplete: true, setting a value on the AutocompleteRoot, triggering a blur event and asserting whether the emitted 'update:modelValue' and 'change' events match the intended retention or fallback behavior, and (2) verify interaction with the multiple prop by mounting InputMenu with autocomplete: true and multiple: true, selecting multiple values via AutocompleteRoot (setValue/clicks) and asserting emitted 'update:modelValue' contains an array of selections and that blur/confirm behavior matches the component's contract; reference the existing tests 'update:modelValue event with autocomplete' and 'change event with autocomplete' to place these new cases.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/content/docs/2.components/input-menu.md`:
- Line 269: The caution line about props when `autocomplete` is `true`
incorrectly lists `displayValue` as a UInputMenu prop; update the sentence for
UInputMenu to either remove `displayValue` from the list or append a brief
clarification that `displayValue` is an internal/option-level field (not a
public UInputMenu prop) so users aren’t misled; locate the text mentioning
`autocomplete` and the list (`multiple`, `by`, `displayValue`,
`resetSearchTermOnSelect`, `resetModelValueOnClear`) and edit it to reflect the
correct public API for UInputMenu.
---
Outside diff comments:
In `@src/runtime/components/InputMenu.vue`:
- Around line 599-613: The template allows the multiple/tags structural path
even when autocomplete mode is enabled, causing an incompatible mix; update the
conditional rendering and related props to ensure the tags/multiple UI is
disabled whenever autocomplete is true (e.g., change v-if="multiple" to
v-if="multiple && !autocomplete" for TagsInputRoot and any other
multiple-specific blocks, and adjust :as-child="!!multiple" to
:as-child="multiple && !autocomplete" or equivalent), and apply the same change
to the other occurrence referenced (lines ~638-649) so all multiple-specific
markup is gated by multiple && !autocomplete.
---
Nitpick comments:
In `@test/components/InputMenu.spec.ts`:
- Around line 167-179: Add regression tests to lock autocomplete-specific
behaviors: extend the InputMenu spec by adding tests that (1) verify blur
retention/defaults when autocomplete is true by mounting InputMenu with
autocomplete: true, setting a value on the AutocompleteRoot, triggering a blur
event and asserting whether the emitted 'update:modelValue' and 'change' events
match the intended retention or fallback behavior, and (2) verify interaction
with the multiple prop by mounting InputMenu with autocomplete: true and
multiple: true, selecting multiple values via AutocompleteRoot (setValue/clicks)
and asserting emitted 'update:modelValue' contains an array of selections and
that blur/confirm behavior matches the component's contract; reference the
existing tests 'update:modelValue event with autocomplete' and 'change event
with autocomplete' to place these new cases.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 3803ce52-278b-4cab-aaa4-fe6e54b72782
⛔ Files ignored due to path filters (2)
test/components/__snapshots__/InputMenu-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/InputMenu.spec.ts.snapis excluded by!**/*.snap
📒 Files selected for processing (4)
docs/app/components/content/examples/input-menu/InputMenuAutocompleteExample.vuedocs/content/docs/2.components/input-menu.mdsrc/runtime/components/InputMenu.vuetest/components/InputMenu.spec.ts
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@docs/content/docs/2.components/input-menu.md`:
- Around line 258-266: The linter flags a setext-style heading because the YAML
frontmatter marker '---' in the ::component-example block is being parsed as an
underline; fix by ensuring the heading "### Autocomplete :badge{label=\"Soon\"
class=\"align-text-top\"}" is followed by a blank line before the
::component-example block (or alternatively replace the leading '---'
frontmatter markers inside the ::component-example with fenced YAML like
```yaml) so the section uses ATX heading style and MD003 is resolved.
In `@src/runtime/components/InputMenu.vue`:
- Around line 385-387: The autocomplete searchTerm is only initialized from
props.modelValue and ignores props.defaultValue, causing empty initial filtering
for uncontrolled usage; update the initialization in the block guarded by
props.autocomplete so that searchTerm.value is set from props.modelValue if
present, otherwise from props.defaultValue, and finally fall back to an empty
string (i.e., use props.modelValue ?? props.defaultValue ?? ''), ensuring this
change affects the existing searchTerm and props.autocomplete logic.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: bb6c8d49-47d5-4954-b4cb-6ff1f95835b2
📒 Files selected for processing (2)
docs/content/docs/2.components/input-menu.mdsrc/runtime/components/InputMenu.vue
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
test/components/InputMenu.spec.ts (1)
168-180: Add a controlled-prop regression test for autocomplete mode.These tests validate emit paths, but not the case where parent updates
modelValuedirectly. Adding that case would guard against input/filter desync regressions in controlled usage.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@test/components/InputMenu.spec.ts` around lines 168 - 180, Add a regression test in InputMenu.spec.ts that covers controlled-prop behavior in autocomplete mode: mount InputMenu with autocomplete: true and items, find the AutocompleteRoot, simulate user input (setValue) then simulate the parent updating the prop by calling wrapper.setProps({ modelValue: 'Option 1' }) (or the appropriate value shape used elsewhere) and assert that the component's input/filter state stays in sync (e.g., the AutocompleteRoot value or displayed suggestions reflect the new modelValue) and that no unexpected emits occur; reference the existing test patterns using mount(InputMenu...), findComponent({ name: 'AutocompleteRoot' }), and wrapper.emitted() to mirror style and assertions.
🤖 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/components/InputMenu.vue`:
- Around line 159-164: Prop `autocomplete` allows string-based runtime updates
but `modelValue`/`defaultValue`/`update:modelValue` are still typed as the
selection-model generics; change typings to use a unified InputMenuModel alias
that can represent either the selection model or string when autocomplete is
true. Update the component props/types: replace direct generic types for
`modelValue` and `defaultValue` with InputMenuModel<...>, update the
`InputMenuEmits['update:modelValue']` type to the same InputMenuModel alias, and
change the type of `highlight.value` to InputMenuModel<...> as well so all
places accept the string form when `autocomplete` is true. Ensure references to
`autocomplete` remain intact and adjust any related utility types or type guards
to discriminate the string model when `autocomplete` is true.
- Around line 383-390: The mounted-only initialization of searchTerm inside
onMounted/nextTick causes it to drift when the parent updates props.modelValue;
add a reactive watcher (e.g., watch or watchEffect) that observes
props.modelValue (and optionally props.defaultValue) and, when
props.autocomplete is true, sets searchTerm.value = String(props.modelValue ??
props.defaultValue ?? '') and when false resets searchTerm.value = ''. Update
the existing onMounted block to remain for initial setup but implement the
watcher to keep searchTerm in sync; reference the onMounted/nextTick
initialization, props.autocomplete, props.modelValue, props.defaultValue, and
the searchTerm ref when adding the watch.
---
Nitpick comments:
In `@test/components/InputMenu.spec.ts`:
- Around line 168-180: Add a regression test in InputMenu.spec.ts that covers
controlled-prop behavior in autocomplete mode: mount InputMenu with
autocomplete: true and items, find the AutocompleteRoot, simulate user input
(setValue) then simulate the parent updating the prop by calling
wrapper.setProps({ modelValue: 'Option 1' }) (or the appropriate value shape
used elsewhere) and assert that the component's input/filter state stays in sync
(e.g., the AutocompleteRoot value or displayed suggestions reflect the new
modelValue) and that no unexpected emits occur; reference the existing test
patterns using mount(InputMenu...), findComponent({ name: 'AutocompleteRoot' }),
and wrapper.emitted() to mirror style and assertions.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 2be4c7e3-0988-43aa-a1a2-fb7b4f14a29d
⛔ Files ignored due to path filters (2)
test/components/__snapshots__/InputMenu-vue.spec.ts.snapis excluded by!**/*.snaptest/components/__snapshots__/InputMenu.spec.ts.snapis excluded by!**/*.snap
📒 Files selected for processing (2)
src/runtime/components/InputMenu.vuetest/components/InputMenu.spec.ts
There was a problem hiding this comment.
♻️ Duplicate comments (2)
src/runtime/components/InputMenu.vue (2)
278-280:⚠️ Potential issue | 🟠 MajorRoot prop forwarding is still mode-locked and leaks blur-reset behavior into autocomplete.
Line 279 picks the forwarding branch once at setup. If
autocompletechanges later, forwarded props won’t switch. Also, autocomplete forwarding still includesresetSearchTermOnBlur(defaulted totrueat Line 263), which contradicts the autocomplete behavior contract.♻️ Proposed fix
const rootPropsPick = reactivePick(props, 'as', 'modelValue', 'defaultValue', 'open', 'defaultOpen', 'required', 'multiple', 'resetSearchTermOnBlur', 'resetSearchTermOnSelect', 'resetModelValueOnClear', 'highlightOnHover', 'openOnClick', 'openOnFocus', 'by') -const rootProps = useForwardPropsEmits(props.autocomplete ? reactiveOmit(rootPropsPick, 'multiple', 'resetSearchTermOnSelect', 'resetModelValueOnClear', 'by') : rootPropsPick, emits) +const comboboxRootProps = useForwardPropsEmits(rootPropsPick, emits) +const autocompleteRootProps = useForwardPropsEmits( + reactiveOmit(rootPropsPick, 'multiple', 'resetSearchTermOnBlur', 'resetSearchTermOnSelect', 'resetModelValueOnClear', 'by'), + emits +) +const rootProps = computed(() => props.autocomplete ? autocompleteRootProps : comboboxRootProps)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/runtime/components/InputMenu.vue` around lines 278 - 280, rootPropsPick is created once at setup using props.autocomplete, so later changes to props.autocomplete won't switch which props are forwarded and autocomplete still receives resetSearchTermOnBlur; make the forwarding reactive to props.autocomplete by deriving rootPropsPick and rootProps from a computed that watches props.autocomplete (use computed(() => ...)) and inside use reactivePick/reactiveOmit based on the current props.autocomplete value, then pass that computed result into useForwardPropsEmits so forwarded props update when props.autocomplete toggles and ensure resetSearchTermOnBlur is omitted for the autocomplete branch (i.e., when computed sees autocomplete true, omit 'multiple','resetSearchTermOnSelect','resetModelValueOnClear','resetSearchTermOnBlur','by' as appropriate).
159-164:⚠️ Potential issue | 🟠 MajorAutocomplete’s string model contract is not reflected in public TS types.
Runtime now treats
modelValueas free-form text in autocomplete mode, butdefaultValue/modelValue/update:modelValue/highlight.valueremain typed as selection-model generics. This makes valid autocomplete usage type-unsafe for consumers.♻️ Typing direction
+type InputMenuModel< + T extends ArrayOrNested<InputMenuItem>, + VK extends GetItemKeys<T> | undefined, + M extends boolean, + Mod extends Omit<ModelModifiers, 'lazy'>, + C extends boolean | object, + A extends boolean +> = A extends true + ? string + : ApplyModifiers<GetModelValue<T, VK, M, ExcludeItem>, Mod> | IsClearUsed<M, C>Then thread
A extends boolean = falsethroughInputMenuProps,InputMenuEmits, and slot payload types so autocomplete mode is strongly typed asstring.#!/bin/bash # Read-only verification: confirm autocomplete is added but model typing is not discriminated by it. rg -n -A2 -B2 "autocomplete\\?:|defaultValue\\?:|modelValue\\?:|'update:modelValue'|'highlight':" src/runtime/components/InputMenu.vueExpected:
autocomplete?: booleanexists, while model-related types still useGetModelValue-based generics without an autocomplete discriminator.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/runtime/components/InputMenu.vue` around lines 159 - 164, Prop types currently always use the selection-model generics, so when autocomplete is true the model types remain incorrect; update the component to thread a boolean generic (e.g., A extends boolean = false) through InputMenuProps, InputMenuEmits and the slot payload types and make GetModelValue conditional on A so that when A is true defaultValue, modelValue, the 'update:modelValue' emit payload, and highlight.value are typed as string instead of the selection generic; adjust all references in InputMenu.vue (InputMenuProps, InputMenuEmits, slot payload types and any usages of GetModelValue/highlight) to use the new A discriminator.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@src/runtime/components/InputMenu.vue`:
- Around line 278-280: rootPropsPick is created once at setup using
props.autocomplete, so later changes to props.autocomplete won't switch which
props are forwarded and autocomplete still receives resetSearchTermOnBlur; make
the forwarding reactive to props.autocomplete by deriving rootPropsPick and
rootProps from a computed that watches props.autocomplete (use computed(() =>
...)) and inside use reactivePick/reactiveOmit based on the current
props.autocomplete value, then pass that computed result into
useForwardPropsEmits so forwarded props update when props.autocomplete toggles
and ensure resetSearchTermOnBlur is omitted for the autocomplete branch (i.e.,
when computed sees autocomplete true, omit
'multiple','resetSearchTermOnSelect','resetModelValueOnClear','resetSearchTermOnBlur','by'
as appropriate).
- Around line 159-164: Prop types currently always use the selection-model
generics, so when autocomplete is true the model types remain incorrect; update
the component to thread a boolean generic (e.g., A extends boolean = false)
through InputMenuProps, InputMenuEmits and the slot payload types and make
GetModelValue conditional on A so that when A is true defaultValue, modelValue,
the 'update:modelValue' emit payload, and highlight.value are typed as string
instead of the selection generic; adjust all references in InputMenu.vue
(InputMenuProps, InputMenuEmits, slot payload types and any usages of
GetModelValue/highlight) to use the new A discriminator.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: ba2547f1-0685-4b4c-8d2c-0b7263e7537b
📒 Files selected for processing (2)
src/runtime/components/InputMenu.vuetest/components/InputMenu.spec.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- test/components/InputMenu.spec.ts
🔗 Linked issue
Resolves #4859, follows-up #6147
❓ Type of change
📚 Description
Integrate Reka UI's new
Autocompletecomponent into theInputMenucomponent.When the
autocompleteprop istrue, theInputMenuusesAutocomplete.RootandAutocomplete.Inputinstead of theirComboboxcounterparts. ThemodelValuebecomes the input text (string) instead of a selected item, turning the component into a free-form text input with optional suggestions.multiple,by,resetSearchTermOnSelectandresetModelValueOnClearare not applicable in autocomplete mode.resetSearchTermOnBlurdefaults tofalsein autocomplete mode.modelValue.📝 Checklist