useScopedNavigation
Scope-aware keyboard navigation registered via KeyboardProvider. Use when navigation should respect the scope stack (e.g., modals, panels).
useScopedNavigation is the provider-backed sibling of useNavigation. It shares the same DOM item-discovery contract and the same options, but registers its keys through KeyboardProvider instead of returning an onKeyDown handler. Because dispatch goes through the provider, navigation participates in the scope stack and can listen at the document level without the list being focused first.
When to use it
- The list is the primary content of a panel, dialog, drawer, or command palette and arrow keys should work immediately.
- Navigation must be suppressed while a deeper scope (a nested overlay) is active.
- You want page-level keys via
focusWithinOnlyrather than wiringonKeyDownonto a focusable container.
For a list embedded inside a self-contained component — a combobox popup, a dropdown — prefer useNavigation; it avoids the provider dependency.
Typing data-value (TValue)
useScopedNavigation re-exposes the same TValue generic as useNavigation. It narrows highlighted, onHighlightChange, onSelect, and onEnter to a literal union for editor convenience, but it is a type assertion, not runtime validation: every value originates from the data-value DOM attribute and is asserted to TValue at the DOM boundary without being checked against the union. Keep your data-value attributes in sync with the union you instantiate, or validate the string inside your callback before relying on it.
Installation
Requires KeyboardProvider and the @diffgazer/keys package, which is not public on npm yet.
Diffgazer packages are not yet published to npm. Until the first release, pack @diffgazer/ui and @diffgazer/keys from the repository and install those tarballs.
@diffgazer/keys requires no CSS or Tailwind setup.
Parameters
Returns
Unlike useNavigation, there is no returned onKeyDown — the provider owns key dispatch.
Keyboard behavior
Editable-target filtering is handled by the provider via allowInInput. Scope resolution means that if a deeper scope is active, this hook's bindings are suppressed until it is popped.
Examples
Scoped navigation in a menu
Two lists with focusWithinOnly
Notes
Requires KeyboardProvider
useScopedNavigation registers keys through the KeyboardProvider context. It must be used within a <KeyboardProvider> tree.
Scope-aware
Navigation bindings respect the scope stack. If a deeper scope is active, this hook's bindings are suppressed.
No onKeyDown needed
Unlike useNavigation, you do not need to wire up an onKeyDown handler. The provider handles key dispatch.
Edge cases
- Missing provider. This hook asserts the provider context on mount and throws a clear error if no
KeyboardProvideris present — unlikeuseKey, it does not silently no-op. scope: null. Passnullto skip registration while a conditional scope is disabled, without removing the Hook call.focusWithinOnly. Set it when several navigable regions share one page-level provider so each region only responds while it holds focus.
Related
useNavigation— the standalone version with anonKeyDownhandler.useScope— push the scope this hook registers under.- Scopes guide — how the scope stack resolves competing bindings.
Source
Highlighted source loads after this disclosure opens. Browse the source repository.