Skip to content

useListFocus

@astryxdesign/core v0.7.1 · useListFocus

Parameters ​

NameTypeDefaultDescription
optionsUseListFocusOptions{}Configuration object for the list focus behavior. All fields are optional.
options.itemSelectorstring'[role="menuitem"]'Selector for the focusable items within the list.
options.boundarySelectorstring—Selector identifying a list boundary, for lists that contain nested lists of the same kind (e.g. a menu with submenu flyouts). When set, item collection and key handling are scoped to this level's own container. Typically '[role="menu"]'.
options.wrapbooleantrueWhether arrow navigation wraps around at the ends.
options.onEscape() => void—Callback when Escape is pressed (e.g. close the menu). Supplying it also consumes the key (preventDefault); without it Escape passes through to the surrounding layer.
options.orientation'horizontal' | 'vertical' | 'both''vertical'Navigation orientation. 'horizontal' uses ArrowLeft/ArrowRight, 'vertical' uses ArrowUp/ArrowDown, 'both' accepts all four arrows. A horizontal list follows the container's writing direction, so RTL swaps the two arrow keys.
options.hasHomeEndbooleantrueWhether Home/End jump to the first/last enabled item.
options.hasPagingbooleanfalseWhether PageDown/PageUp page through a scrolling list: PageDown moves to the last enabled item fully visible in the container, and pressed there again one viewport further; PageUp mirrors it. Neither wraps; in a list that does not scroll they act as End/Home.
options.hasRovingTabIndexbooleanfalseOpt into roving-tabindex ownership: the hook stamps a single tab stop (one item tabindex="0", the rest -1), repairs it as items mount, unmount, or toggle disabled, and moves it with arrow navigation. When false, the hook only moves focus and never touches tabindex.
options.hasCaretGuardbooleanfalseWhen true, arrow keys are not stolen from a nested text input/textarea whose caret is not at the boundary in the direction of travel (or that has a selection), and are never stolen from a nested contenteditable. Preserves inline text editing within the list.

Returns ​

NameTypeDescription
listRefRef<HTMLElement | null>Bind to the list container element.
handleKeyDown(event: KeyboardEvent) => voidKey down handler to attach to the list container.
handleFocus(event: FocusEvent) => voidFocus handler for the container. Keeps the roving tab stop in sync when hasRovingTabIndex is enabled; a no-op otherwise, so it is always safe to attach.
focusItem(index: number) => voidFocus a specific item by index, clamped to the valid range.
focusFirst() => booleanFocus the first enabled item. Returns true when an item was focused.
focusLast() => booleanFocus the last enabled item. Returns true when an item was focused.
ownsEvent(event: KeyboardEvent) => booleanWhether a key event belongs to this list level rather than a nested list sharing the same boundarySelector. Always true when no boundarySelector is set. Use it to guard consumer-added key handling (Enter/Space, typeahead).
getItems() => HTMLElement[]This level's focusable items in DOM order, already scoped by boundarySelector and with hidden ones dropped. Build typeahead targets from this instead of re-querying.