a11y-kit 0.1.0

Accessibility semantics layer for the estate — platform-free semantic node model (role, name, states, relations), tree audit as a CI gate, AccessKit conversion behind a feature. The layer nobody funds, owned
Documentation
  • Coverage
  • 100%
    76 out of 76 items documented1 out of 1 items with examples
  • Size
  • Source code size: 39.3 kB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 500.0 kB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 5s Average build duration of successful builds.
  • all releases: 4s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • Homepage
  • Repository
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • WyattAu

a11y-kit

The accessibility semantics layer for the estate — the keystone nobody in the ecosystem funds (ADR-0004 §2; measured Oct 2026: AccessKit runs on one maintainer's spare time, has no web adapter, and no project ships an a11y CI gate).

use a11y_kit::{A11yNode, A11yRole, A11yTree, NodeId, Relation, States};

let mut tree = A11yTree::new();
let window = tree.push(A11yNode::new(NodeId(0), A11yRole::Window, "Chisel Docs"));
let toolbar = tree.push(
    A11yNode::new(NodeId(1), A11yRole::Toolbar, "Tool palette")
        .with_parent(window)
        .with_states(States { focused: true, ..States::default() }),
);
tree.push(
    A11yNode::new(NodeId(2), A11yRole::Button, "Save document")
        .with_parent(toolbar)
        .with_relation(Relation::LabelledBy(toolbar)),
);
assert!(tree.audit().is_ok());

The gate

tree.audit() enforces five rules headlessly in CI:

  1. ids are unique;
  2. parents and relation targets resolve;
  3. no parent cycles;
  4. every interactive role carries an accessible name;
  5. at most one focused node, and it lives inside a Window subtree — the "focus is somewhere the screen reader can't see" bug.

Every failure names the node (AuditError::MissingAccessibleName(NodeId(5))), because a gate that cannot be acted on is not a gate.

Properties

  • L1 substrate — dependency-free by default (thiserror only); AccessKit transport conversion lands behind the accesskit feature (Wave 2.1) so the audit layer stays headless and any CI can run it.
  • Toolkits lower into this model; none of them own the gate.

Licensed under MIT OR Apache-2.0.