Keyboard Accessibility and Event Handling
Keyboard interactions should be implemented with appropriate event handling while preserving native browser behavior, focus management, and equivalent functionality for keyboard users. Prefer semantic HTML and native controls before adding custom keyboard logic.
Keyboard accessibility means every interactive operation that can be performed with a mouse or pointer should also have an appropriate keyboard interaction. Native elements such as `button`, `a`, `input`, and `select` already provide much of this behavior, so they should generally be preferred over clickable generic elements.
For keyboard event handling, `keydown` is commonly used when an interaction needs to respond as a key is pressed, such as handling `Enter`, `Space`, or navigation keys. The event exposes information such as `key`, `code`, modifier states, and the target element. Prefer `event.key` when the behavior depends on the meaning of the key, because it represents the key value rather than its physical keyboard position.
Custom widgets require explicit focus and keyboard behavior. A component that behaves like a menu, dialog, tablist, or combobox needs predictable focus movement, appropriate keyboard commands, and visible focus indication. Do not remove focus outlines unless you replace them with an equally clear focus style.
Avoid intercepting keyboard events unnecessarily. Calling `preventDefault()` can suppress useful browser behavior such as scrolling, text editing, form interaction, or native control activation. Only cancel the default action when the custom interaction intentionally replaces it and the replacement remains accessible.
Mouse-only event handlers are a common accessibility defect. If an interaction is genuinely a button, use a native `button` rather than attaching `click` behavior to a `div`; this provides keyboard support, semantics, focus behavior, and assistive-technology information without recreating them manually.
Key points
- Prefer semantic native controls over custom keyboard implementations.
- Use `keydown` when behavior needs to react to key presses.
- Use `event.key` when handling semantic keys such as `Enter`, `Escape`, or `ArrowDown`.
- Preserve visible focus and predictable focus movement.
- Avoid unnecessary `preventDefault()` and mouse-only interactions.
Interview questions
How would you design keyboard support for a custom menu or composite widget?
First, I would determine whether an existing native element can provide the required semantics and interaction. If a custom widget is necessary, I would define its focus model, supported keys, focus movement, activation behavior, and visible focus state according to the appropriate accessibility pattern. I would also ensure that pointer and keyboard interactions expose equivalent functionality and test the component using keyboard-only navigation and assistive technology.
Why should you prefer a native button over a clickable div?
A native `button` already has the correct semantic role and is keyboard accessible by default. It can receive focus and supports standard keyboard activation without manually reproducing browser behavior. A clickable `div` requires additional semantics, focus handling, and keyboard logic, which creates more opportunities for accessibility bugs.
When would you use `keydown` for a keyboard interaction?
Use `keydown` when the application needs to react while a key is being pressed, such as implementing keyboard navigation or responding to `Escape` in a custom component. The handler can inspect `event.key` to determine the intended key. However, native controls should usually be allowed to provide their own standard keyboard behavior instead of duplicating it.
What accessibility problems can arise from calling `preventDefault()` in keyboard handlers?
`preventDefault()` cancels the browser's default action for an event. If used indiscriminately, it can interfere with scrolling, text editing, form controls, or other expected browser behavior. It should therefore be used only when the application deliberately replaces the native behavior with an equivalent interaction.
How do you prevent a frontend feature from becoming mouse-only?
I start with semantic HTML so the browser supplies keyboard behavior where possible. For custom interactions, I identify the equivalent keyboard operation and make focusable elements reachable through normal keyboard navigation. I then test the complete interaction without a mouse, including focus visibility, activation, navigation, and returning focus after transient UI closes.