Tasks.md icon indicating copy to clipboard operation
Tasks.md copied to clipboard

Implemented keyboard (arrow/vim) navigation

Open instance-id opened this issue 5 months ago • 4 comments

Add Comprehensive Keyboard Navigation

Summary

Adds full keyboard navigation support for managing cards and lanes without requiring mouse interaction.

Important

Please note that web (js/ts) programming is not my forte, so I relied heavily on Claude 4.5 for much of this implementation, but with very heavy and thorough guidance and dozens of iterative local builds and testing. That said, if you are not interested in this PR, I can understand. It was fully intended for my own personal use on my local machine via PWA install (using Firefox).

Changes

Navigation

  • Arrow keys / vim keys (h/j/k/l): Navigate between cards and lanes
  • Auto-focus: First card in first lane is focused on app load
  • Empty lane handling: Navigation skips empty lanes when moving left/right

Card Movement

  • Alt+Arrow keys: Move cards between lanes (left/right) or reorder within lanes (up/down)
  • Focus preservation: Card remains focused after being moved

Focus Management

  • Auto-restore: Focus returns to card after creating, renaming, or closing expanded view
  • Escape key: Clears focus and returns to main board
  • Expanded card: Escape key closes dialog

Help Dialog

  • ? key: Opens styled keyboard shortcuts dialog

Modified Files

  • frontend/src/App.jsx: Main keyboard navigation logic, card movement functions, help dialog
  • frontend/src/components/card.jsx: Modified key handler to allow arrow keys to bubble up
  • frontend/src/components/expanded-card.jsx: Added Escape key handler
  • KEYBOARD_SHORTCUTS.md: Updated documentation with new shortcuts

Testing

  • [x] Navigation works in all directions
  • [x] Alt+Arrow keys move cards correctly
  • [x] Empty lanes are skipped during navigation
  • [x] Focus is preserved after card operations
  • [x] Help dialog displays correctly
  • [x] Escape key closes dialogs and clears focus

Breaking Changes

None found. Bulk operations still operate as expected in my testing.

Example of usage:

Video clip of "in action"

https://github.com/user-attachments/assets/c37f7e2a-9de5-4e38-9a15-dab55ac44d2b

"?" triggered shortcut menu

image_20251109181346

instance-id avatar Nov 10 '25 00:11 instance-id

Hey, thanks for the work! I'm actually really interested in that PR. Improving accessibility was always a goal and full keyboard navigation is definitely a huge improvement, I actually see myself fully using it.

I'm going to test and review it soon, hopefully we can have it merged and available in next release within this week

Also, the vim keys and shortcuts panel are amazing, thanks a lot for that inclusion

BaldissaraMatheus avatar Nov 10 '25 13:11 BaldissaraMatheus

Awesome, glad to hear. You will have to forgive the lack of finesse with the styling of the panel. I wanted it to match a bit better than just an alert box, but my css skills leave something to be desired, lol.

instance-id avatar Nov 10 '25 15:11 instance-id

Hey, after testing I found some issues that should be addressed before merging with main branch:

In the board

  • Focused card does not need to have the isFocused prop with the blue outline, the standard "focus" style is enough and should mix better with the standard focused elements (consider that users may also move the focus with tab key);
  • Most of the new move functions code is duplicated from the existing handleCardsSortChange function that is triggered when a card is moved within a same lane or between lanes. It requires a single parameter with format { id, targetLane, index }, where id is the card id ("card-${cardName}"), targetLane is the card lane after moved, and index is its index in lane after moved. Those new functions could be highly reduced by calling this function;
  • Make lane focusable (this can be done by simply adding tabIndex={0} to the
    in the lane div) and add shortcuts (alt + arrows/h-l) to be able to move them too

Keyboard shortcuts dialog

  • All styling from html should be moved to the css index file;
  • Close button on top right should look the same as the one in the expanded-card component;

If you can work on any of those things it would be great, most of it should be pretty simple to do. If not, I can work on it later.

BaldissaraMatheus avatar Nov 14 '25 01:11 BaldissaraMatheus

Yeah, sure thing. I will try and get that handled if not tomorrow, then Saturday.

instance-id avatar Nov 14 '25 03:11 instance-id

I am working on getting the changes committed, but here is what the updates are looking like.

https://github.com/user-attachments/assets/ae7d98d0-4119-4542-848f-d208492a5c25

instance-id avatar Nov 16 '25 05:11 instance-id