Skip to content

Add keyboard navigation to Thread message list #2

@jkbrooks

Description

@jkbrooks

Feature Request

Add comprehensive keyboard navigation support to the Thread component's message list, enabling users to navigate through messages without a mouse.

Background

The packages/react/src/primitives/thread/ components currently render a scrollable list of messages via ThreadMessages.tsx and ThreadViewport.tsx. This feature adds accessibility-focused keyboard navigation.

Requirements

1. Navigation Keys

  • Arrow Up/Down: Move focus to previous/next message
  • Home: Jump to first message
  • End: Jump to last message
  • Page Up/Page Down: Move focus by ~5 messages (or viewport height)

2. Focus Management

  • Add tabIndex and focus handling to MessageRoot.tsx
  • Visual focus indicator (ring/outline) when message is focused
  • Focus should follow scroll (auto-scroll to focused message)
  • Initial focus should be on the most recent message when entering the list

3. Accessibility (ARIA)

  • role="listbox" on the message container
  • role="option" on individual messages
  • aria-activedescendant for current focus
  • aria-label for screen reader context

4. Integration Points

Files likely to be modified:

  • packages/react/src/primitives/thread/ThreadMessages.tsx
  • packages/react/src/primitives/thread/ThreadViewport.tsx
  • packages/react/src/primitives/message/MessageRoot.tsx
  • Possibly create a new hook: useThreadKeyboardNavigation.tsx

Acceptance Criteria

  • Can navigate entire message list using only keyboard
  • Focus is clearly visible on the active message
  • Screen readers announce navigation (test with VoiceOver/NVDA)
  • No breaking changes to existing mouse/touch interactions
  • Keyboard navigation works in all Thread variants
  • Unit tests for keyboard event handlers
  • Navigation state resets appropriately on new messages

Non-Goals

  • This PR does NOT implement:
    • Message content editing via keyboard
    • Keyboard shortcuts for actions (copy, delete, etc.)
    • Vim-style navigation (j/k)

Example Usage

// Should work automatically when using Thread.Viewport
<Thread.Root>
  <Thread.Viewport>
    <Thread.Messages />  {/* Now keyboard navigable */}
  </Thread.Viewport>
  <Composer />
</Thread.Root>

Testing Notes

Test keyboard navigation:

  1. Tab into the message list
  2. Press Down Arrow - should focus first/next message
  3. Press Up Arrow - should focus previous message
  4. Press Home - should focus first message
  5. Press End - should focus last message
  6. Verify screen reader announces "Message X of Y"

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions