Basic list
Add keyboard navigation to a list with one keydown listener, keep its normal tab order, and react to each move with onMove.
Add data-keyrove-item and tabindex="0" to each list item, then attach a
keydown listener to the container.
Tab to an item or click it to try the demo:
- ↑ / ↓ move one item.
- Home / End jump to the first or last item.
- PageUp / PageDown move in blocks.
- Argentina
- Australia
- Belgium
- Brazil
- Canada
- Denmark
- Finland
- France
- Germany
- India
- Ireland
- Italy
<ul id="countries" data-keyrove-page-length="5">
<li data-keyrove-item tabindex="0">Argentina</li>
<li data-keyrove-item tabindex="0">Australia</li>
<li data-keyrove-item tabindex="0">Belgium</li>
<!-- … -->
<li data-keyrove-item tabindex="0">Italy</li>
</ul>
import { keyRove } from '@mixedrays/keyrove';
const list = document.querySelector<HTMLElement>('#countries')!;
list.addEventListener('keydown', (e) => keyRove(e));
Tab still visits every item. Use roving tabindex to make the list a single tab stop, or custom keys to change the bindings.
Page length
Set data-keyrove-page-length on the container to choose how many items
PageUp and PageDown move. The
default is 10; this twelve-item demo uses 5. Jumps stop at the first or
last item.
At either end, pressing a key to move farther keeps focus in place and prevents the browser's default action. See looping lists to wrap to the other end.
Reacting to movement
Pass onMove in the second argument to run a callback after focus moves.
It only fires when focus actually changes. This argument also accepts
settings in place of HTML attributes.
list.addEventListener('keydown', (e) => {
keyRove(e, {
onMove: ({ action, to }) => console.log(action, '→', to),
});
});
The readout at the top of the demo shows three outcomes:
- Indigo: focus moved;
onMovefired. - Amber: keyrove handled the key, but focus stayed in place.
- Gray: keyrove left the key to the browser.
Amber and gray readouts use keyRove's return value.
Other handlers can use it to check whether keyrove handled the key.