Context
The current ComponentTree gives tabIndex={0} to every visible node header, meaning Tab cycles through all visible nodes. The ARIA Authoring Practices Guide (APG) recommends roving tabIndex for tree widgets — only the focused node has tabIndex={0}; all others are tabIndex={-1}. Arrow keys move focus within the tree.
This is acceptable at current scale (small demo app Fiber tree). It becomes a usability problem when Will's full fiber tree serialization lands and node counts grow significantly.
Implementation
- Only the currently focused node has
tabIndex={0}; siblings and cousins get tabIndex={-1}
ArrowDown / ArrowUp move focus to the next/previous visible node
ArrowRight expands and moves focus to first child
ArrowLeft collapses or moves focus to parent
Acceptance criteria
References
- Decision 18 in
CLAUDE.md — APG tree widget pattern and roving tabIndex known improvement
Context
The current ComponentTree gives
tabIndex={0}to every visible node header, meaning Tab cycles through all visible nodes. The ARIA Authoring Practices Guide (APG) recommends rovingtabIndexfor tree widgets — only the focused node hastabIndex={0}; all others aretabIndex={-1}. Arrow keys move focus within the tree.This is acceptable at current scale (small demo app Fiber tree). It becomes a usability problem when Will's full fiber tree serialization lands and node counts grow significantly.
Implementation
tabIndex={0}; siblings and cousins gettabIndex={-1}ArrowDown/ArrowUpmove focus to the next/previous visible nodeArrowRightexpands and moves focus to first childArrowLeftcollapses or moves focus to parentAcceptance criteria
tabIndeximplemented per APG tree widget patternonKeyDownexpand/collapse behavior preservedACCESSIBILITY.mdupdatedReferences
CLAUDE.md— APG tree widget pattern and roving tabIndex known improvement