# `StatifierBlocks.Map.Info`
[🔗](https://github.com/riddler/statifier_blocks/blob/v0.44.1/lib/statifier_blocks/map/info.ex#L1)

The Map's description region, as data: one structured description for
every element `StatifierBlocks.Map.graph/2` draws, and one for the
document itself when nothing is selected.

A host draws the region beside the map and keeps it there. It shows the
selected block's description, or `idle/4`'s answer when no block is
selected. It is the screen-reader twin of the map: the map region is
`aria-hidden`, so anything a sighted reader learns by looking at a box
has to be sayable in words here, and every row of the host's list points
at the region with `aria-describedby`.

## Where every fact comes from

Nothing here is a second reading of the document. Every fact is asked of
something the page already builds:

| Fact | Asked of |
|---|---|
| which elements there are, and their ids | `StatifierBlocks.Map.graph/2` |
| how the document finishes | the end marks `StatifierBlocks.Map.graph/2` draws, which its test holds equal to the outline's ends |
| a block's title and sentence | `ViewModel.title/1`, and `ViewModel.sentence/1` with its event names read through the host's `:phrase` |
| a block's note | the block's own `note` field, in the document |
| a block's settings | `ViewModel.shown_fields/1`: the fields the type's `config_schema/1` declares, with their values |
| where a block sits | `ViewModel.positions/1` |
| its outcomes and where each goes | `StatifierBlocks.Describe.outline/3`'s `:sequence` and `:exit` edges |
| the interrupt rules that can leave it | the outline's `:interrupt` edges |
| what an arm goes to | the outline's `:branch` edges |
| what a connector carries | the outline's `:sequence` edge between the same two blocks |
| what a timer edge says, and what a send arms or a rule hears | the outline's `:timer` edges, and a timer edge's line in `Describe.render/2` |
| what a type is for | `StatifierBlocks.BlockType.explain/1` of the block's type, through the palette |
| the key's lines | the `legend` `StatifierBlocks.Map.graph/2` carries |

A type's explanation is the package's: the paragraph its optional
`explain/0` callback answers, else its palette entry's `description`.
Two cases it has no answer for are said here: a block whose type the
palette cannot resolve, and a type that neither explains itself nor
carries a description.

The settings are values, never controls: this is a description, and the
one place a value is changed stays the host's form.

## The note

A block whose document carries an author-written `note` for it has that
note as its description's `note`, and the region shows it above the
built-in text: before the sentence, the type's explanation and the
facts (ADR-0001's Amendment of 2026-09-28, clause `2g`). A block with no
note, or a note that is only whitespace, has `note: nil` and reads as it
did. Only a block, and a rule, which is a block, carries one.

## The host's words

`elements/6` takes the `:phrase` option `StatifierBlocks.Map.graph/2`
takes, a function from an event name to the words a reader reads for it
or `nil`, and reads a block's sentence, a rule's event and a timer
edge's line through it, in the Map's own sentence shapes. A host passes
the same function to both, so the region says what the box says. Without
it every name stays as authored. The places a name is a value rather
than prose keep the name: a block's settings and what a document or a
rule listens for.

## The kinds

An element's `kind` says what it is on the map. `:block` and `:rule` are
boxes for blocks - a rule is a block in a group's interrupt rules;
`:arm`, `:undecided_arm`, `:rules`, `:body` and `:tray` are a block's
slots drawn as boxes of their own, `:body` being a group's body, drawn as
a pane beside its rules; `:marker` is an empty slot's "Nothing here yet";
`:end` is a final mark where the document finishes, one per outcome it
finishes with (`done`, and `abandon` where an interrupt rule abandons a
group in tail position, see `StatifierBlocks.Map`'s "The end"), and each
edge into it is an `:edge` that names the outcome;
`:start` is the filled dot the document starts at, and its edge into the
first step is a `:start` too;
`:edge` is a connector, a branch's rejoin among them; `:interrupt` is
the dashed edge an interrupt rule draws to where it takes its group;
`:timer` is the dotted edge from a send with a delay to the interrupt
rule or the await that hears the event it sends; and `:idle` is the
document, described when nothing is selected. A
branch's description names its arms in order, which is what the band
over them on the map says. Each description is keyed by the id the map
draws it under, so the Map hook, `StatifierBlocksMap`, looks one up by
the element under the pointer without asking the server.

## Hover

Pointing at a drawn element shows that element's description, in the
browser, in a hover layer drawn in the region's place, and pointing away
hides the layer, so the region shows again: the selected block's
description, or the idle one. The region itself is never written on a
hover, so what it announces changes only on a selection. It pushes
nothing and changes no selection. The hook reads two ids off its own
element: `data-info-hover`, the hover layer's, and `data-info-store`, a
hidden element holding one child per description, `data-describes` naming
the map id and its inner markup what the region shows for it. A host that
stamps neither gets a map with no hover.

# `fact`

```elixir
@type fact() :: {String.t(), String.t() | [String.t()]}
```

One labelled fact: a single value, or a list of them.

# `kind`

```elixir
@type kind() ::
  :block
  | :rule
  | :arm
  | :undecided_arm
  | :rules
  | :body
  | :tray
  | :marker
  | :end
  | :start
  | :edge
  | :interrupt
  | :timer
  | :idle
```

What an element is on the map; see the moduledoc.

# `option`

```elixir
@type option() :: {:phrase, (String.t() -&gt; String.t() | nil)}
```

The options `elements/6` takes; see the moduledoc's "The host's words".

# `t`

```elixir
@type t() :: %StatifierBlocks.Map.Info{
  explanation: String.t(),
  facts: [fact()],
  id: String.t() | nil,
  kind: kind(),
  note: String.t() | nil,
  sentence: String.t() | nil,
  settings: [fact()],
  title: String.t()
}
```

One element described. `id` is the map's id for it (`nil` for the idle
description); `note` is the author's note on a block, shown above the
rest, or `nil`; `sentence` is left `nil` where it would only repeat
`title`; `settings` are a block's configured values and `facts`
everything else a reader needs, both in reading order.

# `elements`

```elixir
@spec elements(
  StatifierBlocks.Document.t(),
  StatifierBlocks.Map.t(),
  StatifierBlocks.ViewModel.t(),
  StatifierBlocks.Describe.t(),
  StatifierBlocks.Palette.t(),
  [option()]
) :: [t()]
```

Every element `graph` draws, described, in the order a walk of the graph
meets them: a box, then what is inside it, then its connectors.

`document` is the document `view_model` was built from, which a block's
note is read from; `graph` is `StatifierBlocks.Map.graph/2` of
`view_model`, `outline` is `Describe.outline/3` of the same document,
and `palette` is the one both were built with, which a block's
explanation is asked through. `opts` takes `:phrase`, the function the
graph was built with. The graph's timer edges come last.

# `idle`

```elixir
@spec idle(
  StatifierBlocks.Document.t(),
  StatifierBlocks.Map.t(),
  StatifierBlocks.ViewModel.t(),
  StatifierBlocks.Describe.t()
) :: t()
```

The document described, for when nothing is selected: its name and
description, what starts it, how it finishes, what it listens for, how
to read the map, how many steps and open slots it has, and the key: the
line for each mark the map's key names, the `legend` of `graph`, as the
"Legend" fact, since the map itself is hidden from assistive technology.

---

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