Add focus and keyboard navigation
Pibbl can add logical keyboard interaction to explicit Canvas targets. The HTML Canvas remains the one native DOM focus host. Pibbl does not create semantic DOM descendants, ARIA controls, or a screen-reader accessibility tree.
Opt in with policy components
Section titled “Opt in with policy components”import { FocusManagement, KeyboardNavigation, Rectangle, useEventTarget, type PibblNode,} from "@pibbl/core";
interface ButtonProps { onActivate: () => void;}
function Button({ onActivate }: ButtonProps): PibblNode { const path = new Path2D(); path.rect(20, 20, 140, 48); const focus = useEventTarget( { onClick: onActivate, onKeyDown: (event) => console.log(event.key), }, { path, fill: true, cursor: "pointer", keyboardNavigationBounds: { x: 20, y: 20, width: 140, height: 48 }, }, );
return ( <Rectangle pointerEvents="none" style={{ x: 20, y: 20, width: 140, height: 48, fill: "#2563eb", stroke: focus.isFocusVisible ? "#facc15" : undefined, strokeWidth: focus.isFocusVisible ? 4 : 0, }} /> );}
const scene = ( <FocusManagement> <KeyboardNavigation mode="directional"> <Button onActivate={() => console.log("activated")} /> </KeyboardNavigation> </FocusManagement>);Each policy accepts exactly one Pibbl element after empty values are removed. They are transparent preparation boundaries: they do not paint, lay out, own hooks, or change the enhanced child’s component identity. Directional navigation requires focus management on the same root.
Enrollment and interaction
Section titled “Enrollment and interaction”Only logical event targets become candidates. A target enrolls automatically
with onClick, onKeyDown, or onKeyUp; set keyboardFocusable: true to add
another target or false to exclude it. Built-in Canvas drawing creates a
logical target by default, even when passive; pointerEvents="none" removes
that drawing from hit and focus
participation. Propagation-only structural listeners never become candidates.
When useEventTarget() supplies custom geometry and a later drawing primitive
only visualizes it, mark that drawing pointerEvents="none" as in the example.
Otherwise the default-participating drawing would be the topmost logical target.
The manager owns source-order Tab and Shift+Tab traversal, logical
focus/blur/focusin/focusout events, pointer-press focus defaults,
focus-visible modality, and Enter/Space activation. Tab exits naturally at
either end; it does not wrap. KeyboardNavigation mode="directional" ranks
finite keyboardNavigationBounds for non-wrapping arrow movement. Nested
directional boundaries contain their own edges.
useEventTarget() returns { isFocused, isFocusVisible } for rendering. The
snapshot is inert and false without active focus management. Logical focus
state may invalidate a retained Layer containing the changed target.
A root OffscreenCanvas cannot host DOM focus and rejects focus management.
Offscreen layers under an HTML Canvas share the root manager.
Registered @pibbl/three targets derive directional-navigation bounds by
projecting their Three object bounds into the logical render layer. An explicit
keyboardNavigationBounds on a target is interpreted as a layer-local 2D
override. Source-order Tab behavior and the one native Canvas focus host stay
unchanged across the Three-to-Canvas bridge. See Use Three.js inside
Pibbl.
Accessibility responsibility
Section titled “Accessibility responsibility”Canvas pixels and Pibbl’s logical targets expose no names, roles, values, relationships, reading order, text selection, or platform accessibility nodes. Keyboard reachability is not equivalent to screen-reader accessibility.
For every meaningful Canvas interaction, provide an equivalent semantic DOM
experience that the application owns. Depending on the product, that can be a
real button/control beside the Canvas, a synchronized list or table, an
accessible form for editing, a summary plus data download, or an alternate
nonvisual workflow. Keep labels, state, order, validation, and actions derived
from the same application model. Do not hide the only operable controls in an
aria-hidden mirror or imply that logical focus alone makes the Canvas
accessible.
Pibbl intentionally has no hidden editable DOM adapter, semantic overlay, ARIA mapping, live-region API, or generated accessibility tree. The Canvas owner is also responsible for its accessible name and fallback/adjacent explanation.
See the normative focus contract and Canvas accessibility guidance. Executable lessons cover focus management and directional navigation.
Implementation guidance for agents
Section titled “Implementation guidance for agents”Read the Input, focus, and native HTML companion for ownership, adaptation, failure modes, and verification. Agent start provides the version-selection workflow.
Documentation version
Section titled “Documentation version”Documentation built with @pibbl/core 0.0.2, revision c321a83. ALPHA — NOT FOR PRODUCTION USE.