Vize

Composite Navigation

Headless Composite Navigation; covers WAI-ARIA composite widgets, Reka UI Roving Focus, Ariakit Composite.

Package @vizejs/ui/composite-navigation
Maturity stable
Own the source vize lib pull composite-navigation
Requires collection, typeahead
Aliases roving focus, active descendant, composite widget navigation
Covers WAI-ARIA composite widgets, Reka UI Roving Focus, Ariakit Composite

API

createCompositeNavigation

Create an SSR-safe roving-tabindex or active-descendant collection adapter.

function createCompositeNavigation<Key extends CollectionKey, Value>( options: CompositeNavigationOptions<Key, Value>, ): CompositeNavigationController<Key>

useCompositeNavigation

Create a composite adapter disposed with the current Vue effect scope.

function useCompositeNavigation<Key extends CollectionKey, Value>( options: CompositeNavigationOptions<Key, Value>, ): CompositeNavigationController<Key>

eventElement

function eventElement(value: EventTarget | null): Element | null

focusItem

function focusItem( element: Element | null, preventScroll: boolean, errors: unknown[], ): void

revealItem

function revealItem<Key extends CollectionKey, Value>( item: CollectionItem<Key, Value>, custom: ((item: CollectionItem<Key, Value>, event: Event | null) => void) | undefined, event: Event | null, errors: unknown[], ): void

validateActiveDescendant

function validateActiveDescendant<Key extends CollectionKey, Value>( host: Element | null, item: CollectionItem<Key, Value>, id: string, errors: unknown[], ): void

capture

function capture(errors: unknown[], callback: () => void): void

surfaceErrors

function surfaceErrors(errors: readonly unknown[], message: string): void

readBoolean

function readBoolean(source: unknown, name: string): boolean

readOrientation

function readOrientation(source: unknown): CompositeOrientation

readDirection

function readDirection(source: unknown): CompositeDirection

readPageSize

function readPageSize(source: unknown): number

readStrategy

function readStrategy(value: unknown): CompositeFocusStrategy

keyIntent

function keyIntent( event: KeyboardEvent, orientation: CompositeOrientation, direction: CompositeDirection, ): CompositeNavigationCommand | null

validateId

function validateId(value: unknown): string

validateOptions

function validateOptions<Key extends CollectionKey, Value>( options: CompositeNavigationOptions<Key, Value>, ): CompositeFocusStrategy

isEditableDescendant

function isEditableDescendant(event: KeyboardEvent): boolean

validateCommand

function validateCommand(value: unknown): CompositeNavigationCommand

Behavior

createCompositeNavigation adapts one CollectionRegistry to either WAI-ARIA focus-management strategy. It owns logical navigation and DOM focus representation; roles, labels, selection, activation, and styling remain consumer-owned.

Concern Contract
Server rendering Construction and prop reads require no browser globals. IDs come from consumer data, not request-global counters.
Hydration Server markup hydrates in place; stable prop handlers begin navigation without replacing the host.
Vapor The public composable fixture must compile in native DOM, SSR, and Vapor lanes without diagnostics.
Roving focus Exactly the effective active item receives tabindex="0"; all other registered items receive -1.
Active descendant The container receives tabindex="0" and the active item's validated, stable ID. Items keep DOM focus off themselves.
Initial state Before explicit activation, the first navigable item is the effective tab stop or active descendant.
Disabled items Registry policy determines navigability. Default skip behavior omits disabled items from every command and typeahead.
Arrow keys Orientation gates horizontal and vertical arrows. Horizontal movement reverses under reactive RTL direction.
Boundaries loop affects arrows only; Home, End, PageUp, and PageDown remain deterministic.
Paging pageSize counts navigable items, never disabled records, and clamps at collection boundaries.
Editable descendants Keyboard events from text-entry inputs, selects, textareas, or contenteditable descendants are not consumed.
Modified input Composition and Alt, Control, or Meta shortcuts are not interpreted as navigation.
Typeahead Optional Unicode-aware typeahead commits into the same registry state and synchronizes the configured focus strategy.
Pointer and focus Item-owned pointerdown and focus handlers update logical state without duplicating an unchanged transition.
Virtualization Null item elements are valid with active descendant; a custom reveal callback receives the logical item.
Portals Active descendants must be contained, aria-owns related, or inside a controlled popup of a supported input role.
Scrolling Roving focus may use preventScroll; custom reveal takes precedence over the nearest-block fallback.
Callback timing Logical state and DOM representation commit before onNavigate; snapshots are immutable and retain the native event.
Failure atomicity Focus, reveal, and callback failures are surfaced together after committed state remains observable.
Reactivity Orientation, direction, loop, page size, disablement, and typeahead controls are read at event time.
Disposal Disposal is idempotent, releases timers and handler caches, makes container handlers inert, and spares the registry.
Styling The module emits no CSS. Consumers freely apply classes, data attributes, CSS, or design-token presets.
Tree shaking Root and subpath consumers produce identical JavaScript, retain no unrelated family signatures, and emit zero CSS.