B4 — Planner board: keyboard navigation + letter shortcuts #412

Closed
opened 2026-04-27 00:02:38 +00:00 by claude-desktop · 0 comments
Collaborator

As an operator,
I want j/k to move focus between cards and single-letter keys to mutate the focused card,
so that I can triage without touching the mouse — matching the rest of the app (drawer, monitor, agents pages).

The board is mouse-only today. Linear's per-card letter-shortcut model is the reference; Trello pioneered the pattern. This story establishes the focus + keymap infra.

Acceptance criteria

Card focus

  • j / k move focus between cards within the focused column (down / up).
  • h / l move focus between columns (left / right). Focus carries over to the same vertical index when possible; otherwise to the nearest card.
  • Focused card shows a 2 px outline-accent ring with outline-offset-2. Distinguishable from B3's border-accent selection ring.
  • Focus survives SSE-driven cache patches — the focused card stays focused unless it disappears from the projection (then focus moves to the next card in the column, or up to the column header if empty).
  • Focus is restored on route mount from the first card of the first non-empty column.

Letter shortcuts on focused card

  • a opens an agent picker popover anchored to the card. Popover lists all agent types (boss, dev, reviewer, designer, design-reviewer) plus an "Unassign" item. Pick → call assignCard.
  • s opens a stage picker popover (same anchor). Lists the pipeline stage enum. Pick → call restageCard (B2 endpoint). If B2 has not landed yet, hide this shortcut behind a ? placeholder ("Stage change requires B2").
  • r opens the existing reroute confirm dialog (/board/reroute).
  • Enter opens the issue detail (route or drawer — match whatever pattern the rest of the app uses today).
  • Esc closes any open popover or dialog. Falls through to clear B3 selection if no popover open.

Keymap overlay

  • ? shows a keymap overlay listing all board shortcuts (j/k/h/l, a/s/r, Enter, Esc, cmd-a).
  • Overlay is a centered Dialog.Popup with shadow-overlay, dismissable with Esc or click-outside.
  • List is grouped: Navigation / Card actions / Selection.

Scope + cleanup

  • All shortcuts are scoped to the /planner/board route — registered in a useEffect with cleanup on unmount.
  • Shortcuts are suppressed when focus is in a text input, textarea, or contenteditable (standard guard).
  • Shortcuts are suppressed when a popover or dialog is open, except Esc (which closes it).

Tests

  • board.test.tsx: j/k cycles focus within a column.
  • board.test.tsx: h/l moves focus between columns.
  • board.test.tsx: a opens picker → selecting dev calls assignCard with the focused card.
  • board.test.tsx: ? opens keymap overlay; Esc dismisses.
  • board.test.tsx: shortcuts suppressed when focus is in the filter input.

Out of scope

  • Global command palette (cmd-k). Separate spec.
  • Vim-style word motions (w, b, gg, G). Overkill for one operator.
  • Letter shortcuts on hover (Trello pattern). Focus-only is simpler and matches Linear.

References

  • Spec: docs/specs/board-rework.md §5 B4.
  • Existing keyboard patterns in the app: apps/web/src/components/... (search for addEventListener("keydown" to find the convention).
  • B3 (multi-select) overlaps on Esc and cmd-a — coordinate the keymap.

Suggested first commit

feat(board): j/k card focus + a/s/r letter shortcuts + ? keymap overlay

**As an** operator, **I want** `j/k` to move focus between cards and single-letter keys to mutate the focused card, **so that** I can triage without touching the mouse — matching the rest of the app (drawer, monitor, agents pages). The board is mouse-only today. Linear's per-card letter-shortcut model is the reference; Trello pioneered the pattern. This story establishes the focus + keymap infra. ## Acceptance criteria ### Card focus - [ ] `j` / `k` move focus between cards within the focused column (down / up). - [ ] `h` / `l` move focus between columns (left / right). Focus carries over to the same vertical index when possible; otherwise to the nearest card. - [ ] Focused card shows a 2 px `outline-accent` ring with `outline-offset-2`. Distinguishable from B3's `border-accent` selection ring. - [ ] Focus survives SSE-driven cache patches — the focused card stays focused unless it disappears from the projection (then focus moves to the next card in the column, or up to the column header if empty). - [ ] Focus is restored on route mount from the first card of the first non-empty column. ### Letter shortcuts on focused card - [ ] `a` opens an **agent picker** popover anchored to the card. Popover lists all agent types (boss, dev, reviewer, designer, design-reviewer) plus an "Unassign" item. Pick → call `assignCard`. - [ ] `s` opens a **stage picker** popover (same anchor). Lists the pipeline stage enum. Pick → call `restageCard` (B2 endpoint). If B2 has not landed yet, hide this shortcut behind a `?` placeholder ("Stage change requires B2"). - [ ] `r` opens the existing **reroute confirm dialog** (`/board/reroute`). - [ ] `Enter` opens the issue detail (route or drawer — match whatever pattern the rest of the app uses today). - [ ] `Esc` closes any open popover or dialog. Falls through to clear B3 selection if no popover open. ### Keymap overlay - [ ] `?` shows a keymap overlay listing all board shortcuts (`j/k/h/l`, `a/s/r`, `Enter`, `Esc`, `cmd-a`). - [ ] Overlay is a centered `Dialog.Popup` with `shadow-overlay`, dismissable with `Esc` or click-outside. - [ ] List is grouped: Navigation / Card actions / Selection. ### Scope + cleanup - [ ] All shortcuts are scoped to the `/planner/board` route — registered in a `useEffect` with cleanup on unmount. - [ ] Shortcuts are suppressed when focus is in a text input, textarea, or contenteditable (standard guard). - [ ] Shortcuts are suppressed when a popover or dialog is open, except `Esc` (which closes it). ### Tests - [ ] `board.test.tsx`: `j/k` cycles focus within a column. - [ ] `board.test.tsx`: `h/l` moves focus between columns. - [ ] `board.test.tsx`: `a` opens picker → selecting `dev` calls `assignCard` with the focused card. - [ ] `board.test.tsx`: `?` opens keymap overlay; `Esc` dismisses. - [ ] `board.test.tsx`: shortcuts suppressed when focus is in the filter input. ## Out of scope - Global command palette (`cmd-k`). Separate spec. - Vim-style word motions (`w`, `b`, `gg`, `G`). Overkill for one operator. - Letter shortcuts on hover (Trello pattern). Focus-only is simpler and matches Linear. ## References - Spec: `docs/specs/board-rework.md` §5 B4. - Existing keyboard patterns in the app: `apps/web/src/components/...` (search for `addEventListener("keydown"` to find the convention). - B3 (multi-select) overlaps on `Esc` and `cmd-a` — coordinate the keymap. ## Suggested first commit `feat(board): j/k card focus + a/s/r letter shortcuts + ? keymap overlay`
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/claude-hooks#412
No description provided.