RootFocusBoundary
The root of a virtual focus tree for a single anchor node
import { RootFocusBoundary } from "@roku-sdk/navigation";RootFocusBoundary(props: IRootFocusBoundaryProps): JSX.ElementDescription
The root of a virtual focus tree for a single anchor node.
RootFocusBoundary owns every anchor-node-wired concern:
keyEvent: the SceneGraph key input it dispatches through the treefocusActive: whether this anchor node holds SceneGraph focussetHandledKeys: thehandledKeysoutput BrightScript reads to claim keyssetFocusPath: optional automation output for the focused leaf's SG path
Nested subtrees use FocusBoundary (with focusId) and receive key events through the dispatch chain.
An app may have more than one RootFocusBoundary — one per anchor node that extends FocusBoundaryBase (e.g. a scene plus a separately-rendered overlay). Each observes its own keyEvent, and only the one in the SceneGraph focus chain is active at a time via focusActive.
Parameters
| Name | Type | Description |
|---|---|---|
props | IRootFocusBoundaryProps | The anchor node's inputs and outputs, and the tree's content. |
Example
const MyScene: AnchorNodeImplementation<typeof Desc> = (inputs, outputs) => (
<RootFocusBoundary
keyEvent={inputs.keyEvent}
focusActive={inputs.focusActive}
setHandledKeys={outputs.handledKeys}
setFocusPath={outputs.focusPath}
initialFocus={itemId}
navigation="vertical"
>
<MenuItem focusId={itemId} label="First" />
<MenuItem label="Second" />
</RootFocusBoundary>
);Types
IRootFocusBoundaryProps
Props for the RootFocusBoundary component.
| Name | Type | Description |
|---|---|---|
captureKeyPress? | boolean | When true, a key-down consumed by a handler this boundary owns binds the matching key-up to that handler. See IFocusBoundaryProps.captureKeyPress. |
children? | Element | The focus tree's content. Descendants that call useFocusable register with this boundary, unless a nearer FocusBoundary sits between them. |
focusActive? | boolean | Reactive signal indicating whether this anchor node currently has SceneGraph focus. Wire from the anchor node's focusActive input field. See IFocusBoundaryProps.focusActive. |
handleAllKeys? | boolean | When true, the boundary claims ALL key events unconditionally. See IFocusBoundaryProps.handleAllKeys. |
initialFocus | object | The focusId object that will receive virtual focus when the boundary mounts. Must match the focusId (UseFocusableOptions.focusId) passed to one of the descendant useFocusable calls. |
keyEvent? | RemoteKeyEvent | null | The reactive key event from the anchor node's keyEvent input field. See below. |
navigation? | "vertical" | "horizontal" | "grid" | Navigation direction used when the focused component does not consume a directional key. See IFocusBoundaryProps.navigation. |
navigationMap? | NavigationMap | Explicit navigation map for irregular layouts. See IFocusBoundaryProps.navigationMap. |
onUnhandledKey? | KeyPressHandlerMap | Declarative boundary-level key handlers. See IFocusBoundaryProps.onUnhandledKey. |
setFocusPath? | (path: string) => void | Opt-in automation output. See below. |
setHandledKeys? | (keys: Record<string, boolean>) => void | Output setter for the handledKeys SceneGraph field on the anchor node. Pass outputs.handledKeys. See IFocusBoundaryProps.setHandledKeys. |
IRootFocusBoundaryProps.keyEvent
The reactive key event from the anchor node's keyEvent input field.
The anchor node must extends: "FocusBoundaryBase" as const and declare keyEvent: FieldType.Object() as an input field; forward the reactive value here so this boundary becomes the dispatch entry point for the virtual focus tree.
IRootFocusBoundaryProps.setFocusPath
Opt-in automation output. When provided, RootFocusBoundary renders a wrapper <group>, tracks which SceneGraph node currently holds virtual focus, and writes the focused leaf's "/"-separated SG child-index path (e.g. "0/1/0/3/0") through this setter — clearing to "" when nothing is focused or focusActive is false.
Pass the anchor node's focusPath output field:
<RootFocusBoundary
keyEvent={inputs.keyEvent}
focusActive={inputs.focusActive}
setHandledKeys={outputs.handledKeys}
setFocusPath={outputs.focusPath}
initialFocus={itemId}
>When omitted, no wrapper <group> is rendered and no path tracking occurs — the root boundary stays node-less.
Updated about 3 hours ago