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
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions