Prompt and scope
This frontend question tests the keyboard model and accessibility of a complex interaction. Do not just attach a few keydown handlers; define the complete open, search, select, execute, close, and focus-restore state machine and expose the right roles, names, and states to screen readers.
What the interviewer is evaluating
- Whether you distinguish dialog, combobox, listbox, and menu semantics.
- Whether Tab, arrows, Enter, Escape, Home, and End have consistent behavior.
- Whether focus visibility, restoration, dynamic results, loading, and errors are handled.
- Whether global shortcuts avoid stealing input, assistive technology, or browser defaults.
Clarifying questions to ask first
Confirm whether commands are grouped, recent, or asynchronously searched, whether mobile has another entry point, whether shortcuts are configurable, and whether execution navigates, opens a dialog, or changes page state. Also clarify mouse and touch support, result limits, and acceptable loading delay.
A 30-second answer structure
Use a named modal dialog around an input and results with an explicit combobox/listbox relationship. Save the trigger and focus the input on open; arrows move the active item, Enter executes, and Escape closes and restores focus. Announce result state changes, trigger shortcuts only in safe contexts, and test every transition with keyboard, a screen reader, and automation.
Deep-dive answer
1. Choose the semantic boundary
Use a named dialog outside, combobox semantics for the input when the interaction calls for it, listbox for results, and option for choices. For hierarchical commands, follow a menu pattern instead of adding role="menuitem" everywhere. ARIA should describe real behavior, not mask an incorrect DOM structure.
2. Design the focus and keyboard state machine
Record the trigger and focus the input on open. Arrow keys move through results, Home and End jump to boundaries, Enter executes the current item, and Escape closes. Tab behavior must match the chosen pattern and never let focus fall behind the dialog. On close, failure, or navigation, restore focus to the trigger or a sensible target.
3. Handle dynamic results and announcements
Keep input focus while async search updates results, update aria-activedescendant or real focus, and expose loading, empty, error, and result-count states. Do not read the whole list on every character; use a concise status region and make the selected name, shortcut, and disabled state perceivable.
4. Control shortcuts and default behavior
Check current focus, modifier combination, and platform before opening. Avoid stealing shortcuts from inputs, editors, or screen-reader modes. Call preventDefault only when replacing a browser behavior is intentional; preserve copy, paste, find, and assistive operations. Provide a visible button so a shortcut is never the only entry.
5. Make execution, failure, and testing observable
Show the selected command before execution, expose progress or prevent duplicate submits for async work, and keep context with a retry path on failure. Test keyboard-only paths, visible focus, focus traps, Escape restoration, dynamic results, zoom, slow networks, and at least one screen reader. Log opens, searches, failures, and cancellations without recording sensitive input.
Example of a strong answer
I would wrap the input and results in a named dialog. On open, save the trigger and focus the input; connect the input and listbox with aria-controls and aria-activedescendant so the active option is clear. Arrows and Home/End move selection, Enter executes, Escape closes and restores focus, and Tab never reaches the background. Async search announces loading, empty, and error states concisely. Shortcuts check focus and platform, preserve browser defaults, and have a visible button alternative. Tests cover keyboard, screen reader, zoom, slow network, retry, and visible focus, and telemetry excludes sensitive queries.
Common mistakes
- Handling keydown without defining open, close, and focus restoration states.
- Adding menu, menuitem, or combobox roles to arbitrary containers.
- Losing focus after dynamic updates so screen readers cannot identify the active option.
- Intercepting global shortcuts and breaking input, copy/paste, or assistive behavior.
- Offering no visible entry point and requiring users to memorize a shortcut.
- Testing only mouse clicks and automation instead of keyboard, zoom, screen reader, and slow network.
Follow-up questions
Should you move real focus or use aria-activedescendant?
Both can work depending on structure and screen-reader support. Real focus is direct but requires managing input and option interaction; aria-activedescendant keeps input focus and requires stable references, perceivable options, and real-device testing.
How do you avoid a focus trap when there are no results?
Keep focus in the input, show an explicit empty state, and allow Escape, query editing, and visible buttons. Never move focus to a non-interactive placeholder.
Where does focus go after navigation?
The destination should choose a sensible target such as its heading or main content. If the user stays on the page, restore the trigger or context. On failure, keep the palette open with the query and error.
How do you verify shortcuts do not conflict with the browser?
List supported platforms and combinations and test in inputs, editors, forms, and screen-reader environments. Prevent default only when intentionally replacing it, and provide settings or a button alternative.