Grid
Add arrow-key navigation to a grid. Set the column count, then move by cell, row, row ends, grid ends or pages, with arrows that flip in right-to-left text.
Set data-keyrove-cols above 1 to navigate a grid. ↑/↓ move one row in
the same column; ←/→ move one cell in DOM order.
<div id="time-slots" data-keyrove-cols="6" data-keyrove-page-length="2">
<button data-keyrove-item tabindex="0">09:00</button>
<button data-keyrove-item tabindex="0">09:30</button>
<button data-keyrove-item tabindex="0">10:00</button>
<!-- … -->
<button data-keyrove-item tabindex="0">17:30</button>
</div>
import { keyRove } from '@mixedrays/keyrove';
document
.querySelector('#time-slots')
.addEventListener('keydown', (e) => keyRove(e));
The demo sets data-keyrove-cols="6" and data-keyrove-page-length="2", so a
page is two rows. The column count is the one keyrove navigates by, so keep it
in step with the layout: a CSS grid-template-columns of six and a
data-keyrove-cols of four will move focus in a way that does not match what is
on screen.
Moves in a grid
| Move | Default key | Attribute | At the edge |
|---|---|---|---|
| Next cell | → | data-keyrove-next-key | Flows on to the next row's first cell; stops at the grid's last cell |
| Previous cell | ← | data-keyrove-prev-key | Flows back to the previous row's last cell; stops at the first cell |
| Next row | ↓ | data-keyrove-next-row-key | Same column; stops at the bottom |
| Previous row | ↑ | data-keyrove-prev-row-key | Same column; stops at the top |
| Row start / end | Home / End | data-keyrove-home-row-key / data-keyrove-end-row-key | First / last navigable cell of the focused row |
| Grid start / end | Ctrl+Home / Ctrl+End | data-keyrove-home-key / data-keyrove-end-key | First / last navigable cell of the grid |
| Page | PageDown / PageUp | data-keyrove-page-down-key / data-keyrove-page-up-key | page-length rows, same column; an overshoot lands on the grid's last / first navigable cell |
- A cell move follows DOM order, like a caret in text, so the cell pair reaches every cell in the grid.
- Grids never wrap;
data-keyrove-loopis ignored. - A grid is entered from outside by any of its four arrows, landing on the first cell.
- Rebind any move and the replaced default goes back to its browser behavior; see custom keys.
At an edge, the key is still consumed and the readout shows an amber no-op. Holding ↓ at the bottom of the grid therefore does not scroll the page.
Right-to-left grids
Under dir="rtl" the default cell arrows flip: ← is the
next cell and → the previous, each still moving the way
it points on screen. The row arrows and any explicit binding stay put. See
horizontal groups and RTL for how the
direction is resolved.
Responsive grids
The column count is read from the attribute on every keypress, not cached, so a grid whose layout changes only needs the attribute kept current. Responsive grid lets the stylesheet decide it.