Keyboard Navigation in Suggestion Lists
Handle ArrowUp, ArrowDown, Enter, and Escape keys to navigate and select suggestions without a mouse.
Keyboard Navigation in Suggestion Lists is a free React Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the React Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Handling onKeyDown on the Input
Attach the keyboard handler to the onKeyDown event on the input element, not onKeyPress (deprecated) or onKeyUp. keyDown fires before the character appears in the input, which allows you to intercept ArrowDown, ArrowUp, Enter, and Escape before they have any default browser effect.
ArrowDown Key Behavior
When the user presses ArrowDown, increment selectedIndex by 1, clamped to a maximum of suggestions.length - 1: setSelectedIndex(prev => Math.min(prev + 1, suggestions.length - 1)). Also call e.preventDefault() to stop the cursor from jumping to the end of the input text, which is the default browser behavior for ArrowDown in text inputs.
ArrowUp Key Behavior
When the user presses ArrowUp, decrement selectedIndex by 1, clamped to a minimum of 0: setSelectedIndex(prev => Math.max(prev - 1, 0)). You may also choose to clamp to -1 (no selection) when going above index 0, allowing the user to "deselect" and return to typing freely.
Enter Key Behavior
When Enter is pressed and selectedIndex >= 0, select the highlighted suggestion: set inputValue to suggestions[selectedIndex], close the dropdown, and reset selectedIndex to -1. If no suggestion is highlighted (selectedIndex is -1), allow the normal form submit or search action to proceed.
Escape Key Behavior
When Escape is pressed, close the dropdown by setting isOpen to false and reset selectedIndex to -1. Do not clear the input value — the user just wants to dismiss the suggestions without selecting one, keeping their typed text for further editing.
Tab Key Behavior
When Tab is pressed, close the dropdown because the browser will move focus to the next focusable element anyway. Setting isOpen to false on Tab ensures the dropdown does not remain open after focus leaves the input. You do not need to call preventDefault() — let the browser handle the natural tab order.
Visual Highlight for Selected Row
The highlighted suggestion must be visually distinct. Apply an active style to the suggestion at selectedIndex: className={index === selectedIndex ? 'suggestion suggestion--active' : 'suggestion'}. The active state typically uses a background color change, making it clear which item will be selected if Enter is pressed.
Scrolling the Selected Item into View
When the suggestion list has a max-height and scrolls, the highlighted item may scroll off screen during keyboard navigation. Use a ref array to store suggestion DOM elements and call listItemRefs.current[selectedIndex]?.scrollIntoView({ block: 'nearest' }) whenever selectedIndex changes. The nearest block value minimizes scroll amount.
Syncing selectedIndex When Suggestions Change
When the input changes and a new filtered list appears, reset selectedIndex to -1 in the same state update or in a useEffect that depends on the suggestions. Stale indices pointing to removed items would cause the user to select the wrong suggestion.
Full Keyboard Navigation Flow
The complete user flow: user types to filter, ArrowDown highlights first item, more ArrowDown moves through the list, ArrowUp moves back up, Enter selects the highlighted item, Escape dismisses without selecting. This covers all standard keyboard interaction patterns users expect from an autocomplete field.
Preventing Default on Arrow Keys
Always call e.preventDefault() when handling ArrowDown and ArrowUp inside a text input. Without it, ArrowDown moves the text cursor to the end and ArrowUp moves it to the beginning. These cursor movements would conflict with your selected index navigation, creating confusing behavior.
Keyboard Navigation Key Mapping
What should happen when the user presses Enter with a suggestion highlighted at selectedIndex = 2?
Lesson Recap: Keyboard Navigation
Handle onKeyDown on the input. ArrowDown increments selectedIndex (clamped at max), ArrowUp decrements (clamped at 0 or -1), Enter selects the highlighted item, Escape closes without selecting, Tab closes and lets browser move focus. Always preventDefault on arrow keys and scroll the highlighted item into view.
Frequently asked questions
Is the “Keyboard Navigation in Suggestion Lists” lesson free?
Yes — the full text of “Keyboard Navigation in Suggestion Lists” is free to read here on the web, and the React Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the React Academy course, upgrade to CoddyKit PRO.
What will I learn in “Keyboard Navigation in Suggestion Lists”?
Handle ArrowUp, ArrowDown, Enter, and Escape keys to navigate and select suggestions without a mouse. You practise React Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start React Academy?
No prior experience is required. React Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Keyboard Navigation in Suggestion Lists” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this React Academy lesson?
Yes. Every React Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Controlled Input with Suggestion List
- Keyboard Navigation in Suggestion Lists
- Async Suggestions with Debounce
- Accessibility for Autocomplete Widgets