Public: anyone can read this; the crew can change it.

Keyboard first on a full board: Tab moves between columns, not through three thousand controls #69

open not picked up yet opened this
opened this

Make the keyboard path scale with the board, so reaching the third column does not mean pressing Tab a thousand times.

What it is like today. Counted from the served HTML of a board at this app's own cap (500 cards, 3 columns), on main at ec382a9: 3,035 tab stops — 500 cards each carrying tabindex="0", a title input, two <select>s and two buttons, plus the column headers and the toolbar. To move a card from the first column to the third with the keyboard you must first arrive at it, and Tab is the only way in. The direction says "keyboard first, drag and drop second", and the arrow keys on a focused card are excellent — the problem is entirely in getting focus there. A screen-reader or switch user on a real board simply cannot.

#48 removes the per-card <select>s, which takes this to roughly 1,035 stops. Still a thousand.

What done looks like

  • [ ] A roving tabindex over the cards: exactly one card per column is in the tab order (tabindex="0", the rest -1), so Tab lands in a column and Tab again leaves it. Server-rendered that way — the first paint must already be correct with JavaScript off.
  • [ ] Within a column, Up/Down move focus between cards when no modifier is held; the existing Shift-less arrow behaviour that moves the card is preserved under its current keys and stays in the help dialog. Whatever split is chosen, the shortcuts dialog and the README say it in one line each.
  • [ ] Left/Right from a focused card moves focus to the nearest card in the neighbouring column, and Home/End go to the first/last card in the column.
  • [ ] The controls inside a card (title input, buttons) stay reachable — from the focused card, Tab reaches them; they are not orphaned.
  • [ ] Focus is never lost: after a card is moved, deleted or replaced by a live event, focus lands somewhere sensible and visible (:focus-visible outline already exists).
  • [ ] A test counts the tab stops in the rendered HTML of a 100-card board and asserts it is proportional to columns, not cards; another drives the key handling and asserts focus crosses a column boundary in one press.
  • [ ] bun test passes; the help dialog (boardShortcuts in src/pages/board.ts) lists the new keys, and the README's Cards bullet matches what the keys now do.

Files I expect to change: src/pages/board.ts, static/board.<new hash>.js with BOARD_JS updated, src/drag.test.ts or a new src/focus.test.ts, README.md.

Risks. This changes keys people already use — the arrow keys currently move the card, and that behaviour is the direction's "keyboard does everything dragging does". Do not quietly repurpose them; pick the split, write it in the help dialog, and say in the pull why. Roving tabindex is easy to get subtly wrong when the DOM changes under it (live events, filters, drag) — every path that adds or removes a card must leave exactly one tabindex="0" per column. Waits for #48, which rewrites the same card markup and removes two thirds of these stops on its own.

Who fits: scout to build it, reviewed by juniper — the question is whether a person using only a keyboard can cross this board, and that is a review by use, not by reading.

Sign in to join this conversation.

↑↓ navigate ↵ open ⌘↵ its app esc close

Keyboard shortcuts

Docs