Tuix.Focus (tuix v0.1.6)

Copy Markdown View Source

Keyboard focus: which element receives targeted input.

Elements opt into the focus ring with focusable: true and a stable :id prop. The runtime collects the focus order from each rendered tree (depth-first document order), moves focus on Tab / Shift+Tab, and marks the focused element with focused: true — and its ancestors with focus_within: true — before painting so focus styles (:focus_border_color, :focus_bg, and the focus_within_* variants) apply.

These are pure functions over element trees; the runtime owns the state (in Tuix.App private, exposed through Tuix.App.focused/1, Tuix.App.focus/2, and Tuix.App.blur/1).

Summary

Functions

The id of the first focusable element with autofocus: true in document order, or nil. Applied by the runtime on the first frame when nothing is focused.

Finds the focusable element with the given id, or nil.

Marks the focusable element with the given id by setting focused: true in its props, merging in any extra_props (e.g. the runtime injects the cursor offset for focused inputs). Every ancestor on the path to the focused element gets focus_within: true (CSS :focus-within), so wrapper boxes can style themselves while a descendant is focused. With id as nil, returns the tree unchanged.

The id after current in the focus order, wrapping around.

Collects the focus order: ids of focusable elements in depth-first document order.

The id before current in the focus order, wrapping around.

Functions

autofocus(element)

@spec autofocus(Tuix.Element.t()) :: term() | nil

The id of the first focusable element with autofocus: true in document order, or nil. Applied by the runtime on the first frame when nothing is focused.

find(element, id)

@spec find(Tuix.Element.t(), term() | nil) :: Tuix.Element.t() | nil

Finds the focusable element with the given id, or nil.

mark(tree, id, extra_props \\ %{})

@spec mark(Tuix.Element.t(), term() | nil, map()) :: Tuix.Element.t()

Marks the focusable element with the given id by setting focused: true in its props, merging in any extra_props (e.g. the runtime injects the cursor offset for focused inputs). Every ancestor on the path to the focused element gets focus_within: true (CSS :focus-within), so wrapper boxes can style themselves while a descendant is focused. With id as nil, returns the tree unchanged.

next(order, current)

@spec next([term()], term() | nil) :: term() | nil

The id after current in the focus order, wrapping around.

With current as nil (or an id no longer in the order), returns the first id. Returns nil for an empty order.

order(tree)

@spec order(Tuix.Element.t()) :: [term()]

Collects the focus order: ids of focusable elements in depth-first document order.

Raises ArgumentError if a focusable element has no :id prop.

prev(order, current)

@spec prev([term()], term() | nil) :: term() | nil

The id before current in the focus order, wrapping around.

With current as nil (or an id no longer in the order), returns the last id. Returns nil for an empty order.