Skip to content

@real-a11y-dev/core

TL;DR — Extracts a browser-accurate accessibility tree from any DOM element, as plain data (Map<string, SemanticNode>). Zero runtime dependencies. Reach for this when you're building your own tooling on top of the engine; for apps, use one of the wrapper packages.

The extraction engine. Every other package is built on top of this.

Install

sh
# Most apps — dev-only (used in tests or behind a dev gate)
npm install -D @real-a11y-dev/core

# Library authors / tools that ship core at runtime — regular dep or peer
npm install @real-a11y-dev/core

@real-a11y-dev/core has no runtime dependencies. It uses standard DOM APIs only.

Which type of dependency do I need?

  • -D (dev) is the right default for most apps — you're using core inside tests, Storybook, or a dev-only audit panel gated by import.meta.env.DEV / process.env.NODE_ENV. See Keep it out of production.
  • Regular dependency if you're publishing your own package that uses core at runtime (e.g. a new audit tool on top of the engine).
  • peerDependency if you're publishing a library that composes core with other Real A11y packages — lets consumers share a single copy.

Extraction

extractA11yTree(root)

Extracts the accessibility tree from a DOM element.

ts
import { extractA11yTree } from "@real-a11y-dev/core";

const tree = extractA11yTree(document.getElementById("app"));
// tree: { nodes: Map<string, SemanticNode>; rootId: string }

Resolves ARIA roles, computes accessible names via the full ANDC algorithm, detects hidden subtrees, and maps interaction capabilities.

extractDomTree(root)

Same shape as extractA11yTree, but uses raw tag names as roles instead of ARIA roles. Useful when you want to audit DOM structure rather than accessibility semantics.

ts
import { extractDomTree } from "@real-a11y-dev/core";

const tree = extractDomTree(document.querySelector("main"));

Query helpers

findByRole(tree, role, options?)

Returns the first SemanticNode matching the given role, or null.

ts
import { extractA11yTree, findByRole } from "@real-a11y-dev/core";

const tree = extractA11yTree(root);
const submitBtn = findByRole(tree, "button", { name: /submit/i });

Options:

OptionTypeDescription
namestring | RegExpFilter by accessible name. String: exact match (case/whitespace-normalized). RegExp: .test().
levelnumberFilter by heading level (1–6).
checkedbooleanFilter by aria-checked state.
expandedbooleanFilter by aria-expanded state.
selectedbooleanFilter by aria-selected state.
pressedbooleanFilter by aria-pressed state.
disabledbooleanFilter by aria-disabled state.
includeHiddenbooleanInclude nodes in aria-hidden subtrees (default: false).

findAllByRole(tree, role, options?)

Returns all matching nodes as SemanticNode[].

ts
const headings = findAllByRole(tree, "heading", { level: 2 });

Tree traversal

linearize(tree, options?)

Returns all nodes in pre-order (DOM order), skipping hidden nodes by default.

ts
import { linearize } from "@real-a11y-dev/core";

const nodes = linearize(tree);
// SemanticNode[] in DOM order

Options:

OptionTypeDefaultDescription
includeHiddenbooleanfalseInclude aria-hidden subtrees

Structure queries

getOutline(tree)

Returns heading nodes as a flat outline list.

ts
import { getOutline } from "@real-a11y-dev/core";

const outline = getOutline(tree);
// [{ id, level, name }, ...]

getTabSequence(tree)

Returns focusable nodes in computed tab order.

ts
import { getTabSequence } from "@real-a11y-dev/core";

const sequence = getTabSequence(tree);
// SemanticNode[] — positive tabindex ascending, then natural order

Tree diffing

diffTrees(before, after)

Compares two tree snapshots and returns what changed.

ts
import { diffTrees } from "@real-a11y-dev/core";

const before = extractA11yTree(root);
// ...user interaction...
const after = extractA11yTree(root);

const diff = diffTrees(before, after);
// { added: SemanticNode[], removed: SemanticNode[], changed: NodeChange[] }

NodeChange:

ts
interface NodeChange {
  id: string;
  before: Partial<SemanticNode>;
  after: Partial<SemanticNode>;
  fields: string[]; // e.g. ["a11y.name", "a11y.states.expanded"]
}

DOM observation

DomObserver

Watches a DOM subtree for mutations and calls a callback (debounced).

ts
import { DomObserver } from "@real-a11y-dev/core";

const observer = new DomObserver(root, () => {
  console.log("DOM changed, re-extract");
}, 200); // 200ms debounce

observer.start();
// Later:
observer.stop();

Types

ts
import type {
  SemanticNode,
  SemanticTree,
  SemanticNavigatorConfig,
  FindByRoleOptions,
  OutlineEntry,
  NodeChange,
  TreeDiff,
  LinearizeOptions,
  QueryInput,
  TreeMode,
  ActionType,
} from "@real-a11y-dev/core";

Released under the MIT License. · Privacy · Accessibility