tuil
ReferencePackages

@mwillbanks/tuil-focus

Deterministic focus scopes, traversal, and restoration for terminal interfaces.

View rawEdit

Overview

Deterministic focus scopes, traversal, and restoration for terminal interfaces.

@mwillbanks/tuil-focus is independently installable and also participates in the umbrella @mwillbanks/tuil runtime where applicable.

Installation

npm install @mwillbanks/tuil-focus

How it operates

Focus scopes register semantic targets, order traversal deterministically, support directional movement, suspend or restore nested scopes, and expose an observable snapshot.

Documentation flow diagram. register scope; register node; activate; move; suspend/restore; dispose; S0 leads to S1; S1 leads to S2
Documentation flow diagram. register scope; register node; activate; move; suspend/restore; dispose; S0 leads to S1; S1 leads to S2

API

APISignatureDescription
FocusChangeinterface FocusChangePublic interface FocusChange.
FocusDirectiontype FocusDirectionPublic type FocusDirection.
FocusManagerclass FocusManagerPublic class FocusManager.
FocusNodeinterface FocusNodePublic interface FocusNode.
FocusNodeInputtype FocusNodeInputPublic type FocusNodeInput.
FocusProviderfunction FocusProviderPublic function FocusProvider.
FocusScopefunction FocusScopePublic function FocusScope.
FocusScopeDefinitioninterface FocusScopeDefinitionPublic interface FocusScopeDefinition.
FocusTrapfunction FocusTrapPublic function FocusTrap.
useFocusablefunction useFocusablePublic function useFocusable.
useFocusManagerfunction useFocusManagerPublic function useFocusManager.
useFocusScopeIdfunction useFocusScopeIdPublic function useFocusScopeId.

Events and lifecycle

Focus changes are exposed through subscriptions; components use them with useSyncExternalStore rather than a separate event name.

All subscriptions and registrations return a disposer or belong to an owning runtime that disposes them in reverse order.

Example

import { FocusManager } from "@mwillbanks/tuil-focus";

const focus = new FocusManager();
focus.register({ id: "save", scopeId: "dialog" });
focus.focus("save");

On this page