# `Raxol.Core.Accessibility.Projection`
[🔗](https://github.com/DROOdotFOO/raxol/blob/v2.7.0/lib/raxol/core/accessibility/projection.ex#L1)

Projects a declaration Element tree into an accessibility tree.

The accessibility tree is a role/label/state descriptor tree that Surfaces
(MCP, Browser) serialize to drive assistive technology. It is derived from the
same Element tree that `Raxol.MCP.TreeWalker` walks (the `view/1` output synced
to the Dispatcher), so a node here carries the discrete Component props.

For each Element the projection either calls the Component's
`Raxol.Core.Accessibility.Provider.a11y_node/1` (for the ~15 Components that
implement it) or falls back to a default extraction driven by
`Raxol.Core.Accessibility.Roles`. The projection is **total**: it never raises
for any input, defaulting unknown types to `:generic` and rescuing a Provider
that itself raises.

## Dependency direction

This lives in raxol_core (which Browser and MCP both depend on, but which does
NOT depend on main raxol). The `type -> module` map names Component modules in
main raxol; they are resolved at runtime only when loaded, guarded by
`Provider.provider?/1`, so raxol_core stays free of a main-raxol dependency.

# `accessibility_node`

```elixir
@type accessibility_node() :: %{
  role: atom(),
  label: String.t() | nil,
  state: %{optional(atom()) =&gt; boolean() | atom()},
  value: term() | nil,
  children: [accessibility_node()],
  live?: boolean(),
  id: String.t() | nil
}
```

# `by_id`

```elixir
@spec by_id(map() | [map()] | nil, keyword()) :: %{
  optional(String.t()) =&gt; accessibility_node()
}
```

Flat `id -> accessibility_node` map for Surfaces that key ARIA by Element id.

Only nodes with a non-empty binary id are included.

# `descriptor`

```elixir
@spec descriptor(map(), keyword()) :: accessibility_node() | nil
```

Projects a single Element's own descriptor -- role/label/state/value/live?/id
-- WITHOUT recursing its children (children is always `[]`).

For Surfaces that walk the Element tree themselves (e.g. MCP
`StructuredScreenshot`) and only need per-node a11y fields folded in.

# `project`

```elixir
@spec project(map() | [map()] | nil, keyword()) ::
  accessibility_node() | [accessibility_node()] | nil
```

Projects an Element (or list of Elements) into an accessibility node (or list).

## Options

  * `:type_map` - override the declaration-type -> Component-module map
    (defaults to the built-in 16-Component map). Mirrors
    `Raxol.MCP.TreeWalker`'s `context.type_map`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
