Skip to content

Consolidate user search combobox behaviour - #1670

Open
skyfallwastaken wants to merge 3 commits into
mainfrom
amp/consolidate-user-search-20260901
Open

Consolidate user search combobox behaviour#1670
skyfallwastaken wants to merge 3 commits into
mainfrom
amp/consolidate-user-search-20260901

Conversation

@skyfallwastaken

Copy link
Copy Markdown
Member

Summary of the problem

UserPicker had robust user search behaviour, while Admin Timeline duplicated it without request cancellation and could send a second search when Enter was pressed before debounced results arrived.

Describe your changes

Extracted a headless UserSearchCombobox that owns debouncing, cancellation, race sequencing and keyboard state while callers keep their own presentation. UserPicker retains its selected-user card and Timeline retains its multi-user chips, presets and compact search results. Added system coverage for stale responses, Enter request behaviour, listbox semantics and keyboard selection.

Screenshots / Media

No visual changes.

@greptile-apps

greptile-apps Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

The PR extracts shared debounced user-search behavior into a headless Svelte combobox while preserving the distinct UserPicker and Admin Timeline presentations.

  • Centralizes request cancellation, stale-response sequencing, keyboard navigation, and selection state.
  • Updates Timeline to support first-result selection both after results arrive and while a request is pending.
  • Adds system coverage for stale responses, Escape cancellation, listbox semantics, keyboard selection, and early Enter behavior.

Confidence Score: 5/5

The PR appears safe to merge because the previously reported search dismissal and Enter-selection failures are addressed with corresponding regression coverage.

No blocking failure remains.

Important Files Changed

Filename Overview
app/javascript/components/UserSearchCombobox.svelte Introduces the shared combobox state machine and now fully addresses the previously reported Escape and Enter failure paths.
app/javascript/components/UserPicker.svelte Replaces local search state with the shared headless combobox while retaining existing presentation and selection behavior.
app/javascript/pages/Admin/Timeline.svelte Adopts the shared combobox and correctly delegates unhighlighted Enter presses to first-result selection.
test/system/admin/timeline_test.rb Adds focused regression coverage for stale searches, keyboard semantics, early Enter selection, request counts, and Escape cancellation.

Reviews (3): Last reviewed commit: "Handle Enter while user search is pendin..." | Re-trigger Greptile

Comment on lines +137 to +140
if (event.key === "Escape") {
open = false;
return;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Escape does not invalidate search

When an Admin Timeline user presses Escape while a search is in flight, this branch only closes the list without clearing the query, aborting the request, or advancing its sequence. The response therefore remains current and sets open back to true when it completes, causing the dismissed results to reopen with the old query still visible.

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/javascript/components/UserSearchCombobox.svelte
Line: 137-140

Comment:
**Escape does not invalidate search**

When an Admin Timeline user presses Escape while a search is in flight, this branch only closes the list without clearing the query, aborting the request, or advancing its sequence. The response therefore remains current and sets `open` back to true when it completes, causing the dismissed results to reopen with the old query still visible.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Comment on lines +153 to +155
else if (event.key === "ArrowUp") highlight = Math.max(highlight - 1, 0);
else if (highlight >= 0 && highlight < results.length)
select(results[highlight]);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Enter drops first-result selection

When Timeline results are displayed and the user presses Enter without first pressing an arrow key, highlight is still -1, so this handler does nothing. The previous Timeline handler selected results[0] in this state, so direct Enter selection now requires an extra ArrowDown keystroke.

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/javascript/components/UserSearchCombobox.svelte
Line: 153-155

Comment:
**Enter drops first-result selection**

When Timeline results are displayed and the user presses Enter without first pressing an arrow key, `highlight` is still `-1`, so this handler does nothing. The previous Timeline handler selected `results[0]` in this state, so direct Enter selection now requires an extra ArrowDown keystroke.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Comment on lines +322 to +334
onkeydown={(event) => {
if (
event.key === "Enter" &&
open &&
highlight === -1 &&
results[0]
) {
event.preventDefault();
select(results[0]);
} else {
handleKeydown(event);
}
}}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P1 Early Enter drops selection

When a user enters a valid query and presses Enter during the debounce interval or before the request completes, this wrapper delegates to handleKeydown because open is false. That handler prevents the default action but has no highlighted result to select, so no immediate request occurs and no user is added.

Prompt To Fix With AI
This is a comment left during a code review.
Path: app/javascript/pages/Admin/Timeline.svelte
Line: 322-334

Comment:
**Early Enter drops selection**

When a user enters a valid query and presses Enter during the debounce interval or before the request completes, this wrapper delegates to `handleKeydown` because `open` is false. That handler prevents the default action but has no highlighted result to select, so no immediate request occurs and no user is added.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

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