Reordering suggestions causes mis-hits
Aliases: typeahead race · list jumping · item stolen under pointer
What it is
Someone has already moved the pointer or finger onto a row and is about to press; a new filter result arrives and that row becomes another item. The press hits the newcomer, not the aimed-at item. Suggestion-list churn is an async update racing an aiming movement. The issue is an item being swapped under the pointer, not whether the list covers the field, and not whether arrow keys work.
Why it happens
Aiming needs the target to stay put until press. Autocomplete results often lag the key: debounce, network, ranking. Each replacement can change row geometry—a more “relevant” item inserts above, the old third row becomes the fifth, the pointer still sits on the old coordinates. Touch has no hover preview, so the problem is harder: if the list refreshes between press and release, release hits the new row. Keyboard highlight bound to a row index rather than a stable id jumps to another object after refresh. This is a classic pointing-stability failure, the same temporal class as clicking a button that a menu has not yet covered.
Studying it
Use a fake API with tunable delay so the list inserts a new item while the pointer already rests on row N; record hits on the target versus the replacement. Factors: whether update keeps scroll, whether highlight is kept by id, debounce. Outcomes: mis-hit rate, angry reopening of the list. A recording on slow 3G is more useful than localhost. Do not test only on instant local results—churn often refuses to appear on a lab LAN.
Where it stops holding
When results are local, synchronous, and back within milliseconds of each key, the churn window is tiny and mis-hits are rare. While the user is still typing in the slot and the pointer has never entered the list, updates are expected, not mis-hits. Speech that dumps a whole word will reshuffle the list; wait for a pause before updating. Screen-reader users who heard “third item” get a different object in third after refresh; the auditory channel churns too.
Applying it
- Once pointer or finger enters the list, freeze that batch until leave or select; queue new results rather than inserting during aim.
- Bind highlight and selection to item id, not row index; after refresh, keep highlighting the same object, or drop highlight if it is gone.
- Floor the interval between network replacements so every key does not reshuffle.
- Verify by slowing the API and parking the pointer on the second item through a refresh. If the click becomes another item, churn is still there. On touch, press without release and watch whether the list changes row under contact.