App provides for a typical application. App scopes the provider to its content root and enables automatic initial focus, which gives Meta Ray-Ban Display users consistent directional navigation without additional setup.FocusNavigationProvider owns directional focus for a subtree. It responds to arrow keys by moving focus to the nearest eligible element. If no candidate is available, it offers movement to the owning scroll container and then reports a boundary to the focused control for rubber-band feedback.useFocusNavigation() when the application needs to request focus movement through the active provider.import { useRef, type ReactNode } from 'react';
import { FocusNavigationProvider } from '@wearables-ui-toolkit/mrbd';
export function EmbeddedSurface({ children }: { children: ReactNode }) {
const containerRef = useRef<HTMLDivElement>(null);
return (
<FocusNavigationProvider containerRef={containerRef}>
<div ref={containerRef} className="embedded-surface">
{children}
</div>
</FocusNavigationProvider>
);
}
import { Button, useFocusNavigation } from '@wearables-ui-toolkit/mrbd';
export function AdvanceControl() {
const { moveFocus } = useFocusNavigation();
return <Button title="Next" onActivate={() => moveFocus('down')} />;
}
FocusNavigationProvider from the package root; it has no per-component subpath.FocusNavigationProviderProps. The component accepts no DOM attributes and does not forward a ref.| Prop | Type | Default | Description |
|---|---|---|---|
children | ReactNode | — | Required. The subtree that participates in focus navigation. |
enabled | boolean | true | Turns the provider’s key and pointer handling on or off. When off, useFocusNavigation().isActive reports false. |
containerRef | RefObject<HTMLElement \| null> | — | Existing element to scope focus queries to. Without it, the provider renders its own full-size wrapper. |
blockTabNavigation | boolean | false | Blocks native Tab traversal so movement is arrow keys only. |
autoFocusFirst | boolean | false | Lets the focus coordinator claim the top-left eligible interactable on mount and on page change. App enables this. |
useFocusNavigation() returns the nearest provider’s contract. Outside a provider, it returns an inert value: isActive is false, moveFocus returns false, and the other two members have no effect.| Member | Type | Description |
|---|---|---|
isActive | boolean | Whether the provider is enabled. |
moveFocus | (direction: 'up' \| 'down' \| 'left' \| 'right') => boolean | Runs one directional search. Returns whether anything moved — either focus changed or a scroll container consumed the movement. |
activateFocused | () => void | Activates the element that currently has focus. |
clearFocus | () => void | Pulls focus back to the first eligible control when focus has escaped the container or rests on the container element itself. Does nothing while a control inside the container already owns focus. |
inert, aria-hidden, fully transparent, zero-sized, or clipped outside their scroll viewport are not candidates. Elements that resolve to pointer-events: none are also excluded. The provider reads only the element’s resolved pointer-events, so a control with pointer-events: auto remains reachable even when an ancestor disables pointer events.Escape uses the same restoration behavior. If focus rests on the container element rather than a control inside it, the provider moves focus to the first eligible element. If a control inside already owns focus, nothing changes. The provider does not consume Escape, so host Back handling continues to run.Enter and Space, allowing the focused control’s native activation behavior to run. Only activateFocused() requests a click on the caller’s behalf.containerRef, the caller’s element owns the focus region and the provider renders no wrapper. Without containerRef, the provider renders a full-size div that is programmatically focusable but is not a tab stop.autoFocusFirst, the focus coordinator focuses the top-left eligible control on the active page. It runs only when the page does not already contain focus, so user, PageTransition, and host-owned focus take priority. Set initialFocusEligible={false} to exclude a control from entry focus while keeping it reachable through directional navigation.blockTabNavigation at its default false for web surfaces. Keyboard and assistive-technology users must be able to leave the region. Enable it only for a surface that is exclusively driven by directional input.preventDefault() for arrow keys it handles, preventing the browser from scrolling for the same input.moveFocus gives the destination the same visual state as arrow-key movement, which keeps the visible focus indicator aligned with actual focus.App as the focus-root owner in a typical application.containerRef when a host element already defines the focus region.moveFocus, activateFocused, and clearFocus instead of dispatching synthetic key events, so provider state and visible focus remain consistent.App already owns that focus scope.blockTabNavigation off on surfaces that keyboard users need to leave; enabling it there would trap focus within the surface.initialFocusEligible={false} to exclude it from entry focus, or disable it when the action is unavailable.