Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

A11yGroupId

Accessibility policies for SceneView.

Two layers cooperate. The visual-default path emits AT nodes for every visible heavyweight widget and every visible lightweight item with role + screen-projected bounds, gated by an A11yOffScreenMode policy that decides which off-viewport items are still announced. The logical-structural API (groups, parents, relations, auto-graft, custom focus callbacks) layers over the top — see docs/teksilo-scene-a11y.md for the full picture.

Defaults are chosen so a quick prototype is accessible out of the box: heavyweight widgets emit normally, lightweight items get synthetic nodes, Tab cycles in reading order. Apps shape the reading experience by declaring A11yGroups, reparenting nodes, and installing a focus-order callback.

Builder methods at a glance

as_u64

API reference

📖 Full rustdoc API for this module

pub struct A11yGroupId

Opaque identifier for a logical AT group declared via Scene::add_a11y_group. Stable across the lifetime of the process; safe to hash, compare, store.

#![allow(unused)]
fn main() {
pub struct A11yGroupId(pub(crate) u64);
}

Methods

pub fn as_u64(self) -> u64

Raw numeric value. Used by the AT walker to derive a synthetic NodeId via synthetic_node_id(scene_view_id, id.as_u64(), SyntheticKind::SceneGroup).

pub enum A11yNode

Address of a node in the parallel logical AT tree. Lets apps uniformly target scene entries, virtual groups, and ad-hoc widgets when declaring relationships, parents, or rotor categories.

#![allow(unused)]
fn main() {
pub enum A11yNode { /* variants */ }
}

Variants

  • Item — Any entry in the scene — lightweight SceneItem or heavyweight Widget added via Scene::add_widget. The walker discriminates by entry kind: lightweight items get a synthetic SyntheticKind::SceneItem AT node; heavyweight items get auto-grafted via the framework redirect hook, landing the real widget's NodeId under the declared parent.
  • Group — A virtual A11yGroup declared via Scene::add_a11y_group.
  • Widget — A real interactive widget addressed by its arena WidgetId. Use this to relocate widgets that aren't Scene::add_widget-managed — typically a descendant of a heavyweight scene item that should logically belong elsewhere (a global ComboBox nested visually inside a Scene card but logically under a top-level "Tools" group). For widgets you added via Scene::add_widget, prefer A11yNode::Item(item_id) — the walker handles the heavyweight-item auto-graft for you.

pub enum A11yRelation

AT relationship kind, applied via Scene::add_a11y_relation. Maps to AccessKit's relationship arrays.

#![allow(unused)]
fn main() {
pub enum A11yRelation { /* variants */ }
}

Variants

  • Controlsfrom controls to (e.g. a button that opens a menu).
  • DescribedByfrom is described by to (cross-item annotation).
  • LabelledByfrom is labelled by to (cross-item label).
  • FlowTo — Logical flow direction — many node-graph editors use this so VoiceOver / NVDA "next item" follows data-flow order rather than reading order.

pub struct A11yCategory

App-defined category tag for AT rotor / quick-nav navigation. Surfaced to AT clients that support categorized navigation (VoiceOver rotor on macOS, NVDA quick-nav). Apps coin their own tag values like "node", "connector", "comment".

#![allow(unused)]
fn main() {
pub struct A11yCategory(pub std::borrow::Cow<'static, str>);
}

Methods

pub fn new(name: impl Into<std::borrow::Cow<'static, str>>) -> Self

Create a new category tag from a string or &'static str. Accepts "node", "connector", String, or any Cow<'static, str>.

pub struct A11yGroupBuilder

Builder for an A11yGroup. Returned by A11yGroup::builder; consumed by Scene::add_a11y_group.

let act_one = scene.add_a11y_group(
    A11yGroup::builder()
        .label("Act 1")
        .role(accesskit::Role::Group)
);
scene.set_a11y_parent(A11yNode::Item(scene_card), Some(A11yNode::Group(act_one)));
#![allow(unused)]
fn main() {
pub struct A11yGroupBuilder { /* fields */ }
}

Methods

pub fn label(mut self, label: impl Into<LocalizedString>) -> Self

Human-readable label for the group, announced when AT clients land on the group node. Accepts anything convertible into LocalizedString.

pub fn role(mut self, role: accesskit::Role) -> Self

Override the AccessKit role. Default: Role::Group. Apps commonly use Role::Region for landmark-style groups.

pub struct A11yGroup

A logical AT group. Pure structure — no visual counterpart, no hit-test, no paint. Declares AT-shape that diverges from visual scene layout (Acts containing Scene cards, Subgraphs containing Nodes, Layers containing Components).

#![allow(unused)]
fn main() {
pub struct A11yGroup { /* fields */ }
}

Methods

pub fn builder() -> A11yGroupBuilder

A fresh builder for a logical group. Default role is Role::Group; override with A11yGroupBuilder::role.

pub fn id(&self) -> A11yGroupId

The group's id. Stable for the lifetime of the process.

pub fn label(&self) -> Option<String>

The label set on the builder, if any.

pub fn role(&self) -> accesskit::Role

The role set on the builder. Default Role::Group.

pub enum A11yMode

AT-emission strategy for SceneView. Decides whether items / widgets that have not been placed in the app-declared logical tree appear in the AT tree by default, or are suppressed.

Pick Cooperative when the visual scene layout is a sensible AT structure for your app (charts, dashboards, simple maps). Pick StrictlyParallel when AT shape diverges meaningfully from visual layout — story corkboards (Acts → Scene cards), node-graph editors (Subgraphs → Nodes → Ports), CAD canvases (Layers → Components). Apps in this category typically declare every AT edge anyway, so the default visual-emission becomes noise.

#![allow(unused)]
fn main() {
pub enum A11yMode { /* variants */ }
}

Variants

  • CooperativeDefault. Visual is the AT structure unless overridden. Items inside the off-screen-mode policy emit as direct AT children of SceneView (or their declared logical parent if set_a11y_parent placed them). Heavyweight widgets emit through the arena walker as natural descendants of SceneView. The logical-tree machinery layers on top.
  • StrictlyParallel — AT structure is purely declared. Items are emitted only if the app placed them in the logical tree via Scene::set_a11y_parent. Heavyweight widgets still emit (they own focus / interaction state the AT layer can't suppress) but their parent in the AT tree is the declared logical parent if any, else SceneView itself. Use this when your app's AT shape is fundamentally different from its visual layout — declaring every node once is cheaper than overriding the visual default for every node.

pub enum A11yBoundsSpace

Coordinate space the AT walker reports SceneItem bounds in.

The framework convention is screen-projected bounds — the rectangle a sighted user would see on the physical monitor, after pan/zoom/rotation has been applied. Screen readers consume this for spatial nav (Apple's "explore by touch", touch-screen navi- gation, magnifier follow-focus). 99% of apps want this default.

Scene bounds are the raw scene-coord rectangle stored on the item, with no view-transform applied. Use this only for the rare AT clients that reason about scene topology rather than viewport position — typically when a SceneView's contents have a logical, fixed coordinate system that the user thinks in (a CAD canvas where "the bracket is at (240, 180)" means a fixed physical machine position regardless of zoom level).

Picking the wrong one makes "go to the next item" navigation either a) ignore the user's current pan (Screen mode in a scene-coord-aware app) or b) report bounds that drift under pan/zoom (Scene mode in a viewport-aware app). Default is Screen — change only when you've confirmed your AT users genuinely want the alternative.

#![allow(unused)]
fn main() {
pub enum A11yBoundsSpace { /* variants */ }
}

Variants

  • Screen — Screen-projected bounds — view_transform * bounds_in_scene. The framework default; matches the convention used by every other widget in the framework.
  • Scene — Raw scene-coordinate bounds, with no view-transform applied. Apps with a logical fixed coordinate system (CAD canvases, blueprint editors) may want this so AT users can reason about "where in the design" an item sits, independent of the current pan/zoom.

pub enum A11yOffScreenMode

Off-screen visibility policy for the AT walker. Decides which scene items get emitted as synthetic AT nodes per AT-rebuild.

ViewportPlusN { n: 1 } is the default: an item appears in the AT tree if its bounds_in_scene intersects viewport ∪ (1× viewport-grown-rect). That keeps the tree close to "what the user can interact with right now" while letting screen-reader users discover items just outside the visible region by jumping to the next/prev — at which point SceneView::ensure_visible pans the view to bring the focused item into view.

#![allow(unused)]
fn main() {
pub enum A11yOffScreenMode { /* variants */ }
}

Variants

  • AllItems — Emit every item in the scene as a synthetic AT node. Heaviest mode — appropriate for small scenes (< ~500 items) where AT users want a complete table of contents.
  • ViewportPlusN — Emit items inside the viewport plus an n × viewport-grown margin around it. n = 0 collapses to "viewport only" with the same allocation pattern as ViewportOnly. n = 1 is the default — gives screen-reader users a one-screen "lookahead" to navigate without ensure_visible round-tripping through pan animation.
  • ViewportOnly — Strict: only items intersecting the current viewport. Pairs with apps that have very large scenes where listing off-screen content would overwhelm AT clients.

Methods

pub fn at_visible_region(&self, visible_scene_region: Rect) -> Option<Rect>

Compute the scene-coord rectangle a given mode considers "AT-visible" given the current visible scene region. Used by SceneView::accessibility as the spatial-index query rect. AllItems returns None so the caller knows to bypass the query and emit every item.