useTreeFocus
Manages roving-tabindex focus and the WAI-ARIA tree keyboard model. ArrowUp/ArrowDown/Home/End roam linearly over the visible treeitems (skipping disabled ones), while ArrowRight/ArrowLeft carry tree semantics (expand/collapse, move to first-child/parent). Enter/Space activate, and printable characters trigger typeahead.
@astryxdesign/core/hooks
Signature
Call shape
useTreeFocus<T extends HTMLElement = HTMLElement>(options: UseTreeFocusOptions = {}): UseTreeFocusReturn<T>Parameters
| Name | Type and behavior |
|---|---|
options | UseTreeFocusOptions · optionalConfiguration object for tree focus behavior. |
options.itemSelector | string · optional · default '[role="treeitem"]'Selector for visible treeitems within the tree, in DOM order. |
options.isItemDisabled | (item: HTMLElement) => boolean · optionalPredicate for whether a treeitem is disabled and must be skipped during navigation. Defaults to reading data-tree-disabled / aria-disabled. |
options.getLevel | (item: HTMLElement) => number · optionalReads the 1-based nesting level of a treeitem. Defaults to the aria-level attribute. |
options.onToggleExpand | (id: string) => void · optionalCalled to expand/collapse the treeitem with the given id (ArrowRight on a collapsed parent, ArrowLeft on an expanded parent, Enter/Space on a parent without its own action). |
options.onActivate | (item: HTMLElement, id: string | undefined) => boolean | void · optionalCalled when Enter/Space activates a treeitem. Return true when handled; return false/undefined to let the hook fall back to toggling expansion. |
options.onActiveChange | (id: string | undefined) => void · optionalNotified when the hook moves focus to a treeitem. Consumers use this to move a single roving tab stop. |
options.hasRovingTabIndex | boolean · optional · default falseWhen true, the hook owns a single roving tab stop across the visible treeitems (stamps tabindex 0/-1, repairs on mount, moves with navigation). Preserves an existing tabindex="0" seed on mount. Attach the returned handleFocus to keep the stop in sync after clicks. |
options.typeahead | boolean · optional · default trueWhether typeahead (jump to next item whose text starts with the typed characters) is enabled. |
Returns
| Name | Type and behavior |
|---|---|
treeRef | React.RefObject<HTMLElement | null>Ref to attach to the tree container element (role="tree"). |
handleKeyDown | (e: React.KeyboardEvent) => voidKey down handler to attach to the tree container. |
handleFocus | (e: React.FocusEvent) => voidFocus handler to attach to the container's onFocus. Keeps the roving tab stop in sync when hasRovingTabIndex is enabled; a no-op otherwise, so always safe to attach. |
focusFirst | () => voidFocus the first enabled visible treeitem. |
focusLast | () => voidFocus the last enabled visible treeitem. |
Usage
Manages roving-tabindex focus and the WAI-ARIA tree keyboard model. ArrowUp/ArrowDown/Home/End roam linearly over the visible treeitems (skipping disabled ones), while ArrowRight/ArrowLeft carry tree semantics (expand/collapse, move to first-child/parent). Enter/Space activate, and printable characters trigger typeahead.
- Use for hierarchical tree widgets: wire onToggleExpand to your expansion state and onActiveChange to a single roving tab stop.
- Attach both treeRef and handleKeyDown to the role="tree" container element.
- Use for linear lists (prefer useListFocus) or 2D grids (prefer useGridFocus); those traversals differ from a tree.