feat: added EsAutocomplete#1777
Draft
ericdouglaspratt wants to merge 24 commits into
Draft
Conversation
Reka auto-highlights the first item whenever results arrive from an empty list, so Enter right after typing selected that item instead of submitting the typed query. Track whether the highlight was user-initiated (arrow keys or pointer movement) and handle Enter in the capture phase on the anchor: a non-user highlight now submits the raw query and stops the event before Reka's own handler can select. Review finding 1 of 10. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ition The submit path now calls preventDefault so a surrounding <form> does not natively submit alongside the component's submit event (Reka only prevents Enter's default when selecting a highlighted item), and ignores the Enter that commits an IME composition, which previously fired submit with half-composed text. Review finding 2 of 10. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The ResizeObserver watches the list container, whose height the trim itself controls, so when available height grew (window resized taller) a trimmed container never resized and the observer stayed silent — the list was stuck at its old item count until the suggestions changed. A window resize now re-measures directly, deferred one frame so the popper's own resize handling updates the available-height constraint first (which also coalesces resize bursts to one measure per frame). Review finding 3 of 10. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
noResults was keyed to the previous query's response, so after an empty result, lengthening the query displayed "No results found" for the new query while its search was still in flight — contradicting the documented behavior. Reset noResults as soon as the query changes above minChars. Review finding 4 of 10. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The blanket mousedown.prevent on the panel blocked focus for any interactive element a consumer renders via the item slot; it now only prevents default for non-interactive targets, and focusout additionally ignores focus moving into the panel so such elements stay usable. focusout also ignores the window itself losing focus (alt-tab, devtools) — the input is still the active element, so the panel no longer disappears mid-interaction. Review finding 5 of 10. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
… machinery The measuring/pending/settledHeight flags and the do-while re-entrancy loop existed only because the ResizeObserver watched the same element whose height the trim itself mutates. The height limit is now read from the container's resolved max-height (desktop popover) or explicit height (mobile takeover list) — both stable while items render — so measuring is idempotent and the observer plus all three guards are deleted. Triggers are now explicit: suggestion changes, window resizes, and the mobile shell re-measuring after it sets the list height from the visual viewport. Review finding 7 of 10. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The clear button was Reka's AutocompleteCancel with a tabindex=0 attribute that only overrode the hardcoded tabindex=-1 via undocumented Vue attr-merge order — an in-range reka-ui bump could silently make it keyboard-unreachable. It is now a plain button we fully own (clear + refocus), naturally tabbable. The Enter capture handler now also ignores Enter originating from the clear button so it acts as a click rather than a submit. The mobile shell resolved the panel element with a computed over the non-reactive $el — the exact pattern the desktop shell's comment calls broken. Both shells now share useAutocompleteContentEl, which re-resolves the element when the open state that mounts the panel changes. Review finding 9 of 10. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The shells duplicated ~150 lines each. Consolidated: - panelMessage is computed once in the parent (which owns model, minChars, noResults, and the message texts) and passed down as a single prop, replacing four forwarded props per shell - the shells' withDefaults blocks were dead code — the parent always binds every prop, so shell defaults could never apply and could silently drift; shells now declare plain typed props - Enter/select/clear handling and the user-highlight tracking (byte-identical including comments) moved to a shared useAutocompleteShell composable - the label block and the clear button (with its styles) are now shared es-autocomplete-label / es-autocomplete-clear-button components - the suggestions ref wrapper computeds became toRef(props, 'suggestions') The shells now carry only their genuine differences: popover chrome + focus open/close model vs dialog takeover chrome + visual-viewport handling, and their MAX_VISIBLE caps. Behavior-preserving. Review finding 6 of 10. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…able guards
The debounce timer was cleared at three separate call sites that each had to
remember the same bookkeeping; scheduleComplete/cancelPendingComplete now
centralize it, so a future terminal path can't forget the cancel and
re-introduce the late-response-reopens-panel bug.
Removed the 'model.value ?? empty-string' guards that spread to eight sites:
defineModel<string>({ default: '' }) makes undefined unrepresentable through
the typed API, so the branches were unreachable and implied a contract that
does not exist.
Deliberately NOT adopted from the review: replacing the timer with @vueuse
watchDebounced (it would be this source-shipped package's first direct
@vueuse/core import, and the dependency is a devDependency — a runtime
resolution risk for consumers not worth taking here), and DS-wide
consolidation of the overlay/label markup with es-menu-bar/es-form-input
(requires an es-ds-styles change; the autocomplete-internal copies were
already deduplicated in the previous commit).
Review finding 8 of 10.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- watch suggestions with depth 1 so apps that mutate the array in place (push/splice) still update noResults and re-trim the list - guard against toLowerCase changing string length (e.g. İ), which would misalign highlight segment offsets; fall back to case-sensitive matching - share one EMPTY_SUGGESTIONS constant so the below-minChars computed is referentially stable and doesn't re-fire downstream watchers per keystroke - coalesce visualViewport resize handling to one layout read/write per frame during the mobile keyboard animation - docs: add the v-model row to the props table (per the text-input page precedent) - import splitAutocompleteText explicitly in the component (matching the explicit-utils-import precedent set by es-menu-bar) - gitignore .playwright-mcp/ browser-session artifacts Review finding 10 of 10. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🔗 Linked issue
❓ Type of change
📚 Description
- a thorough, line-by-line code review
- probably a complete rewrite of the docs page to be more concise and with clearer, more consistent examples
- accessibility testing
- mobile device and browser testing
- a POC integration with the downstream functionality to ensure it can work with that
- removal of the
docs/plansmarkdown file once complete🥼 Testing
🧐 Feedback Requested / Focus Areas
📝 Checklist