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 |
| 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 |
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 its
last step), and the 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.
Summary
Types
One labelled fact: a single value, or a list of them.
What an element is on the map; see the moduledoc.
The options elements/6 takes; see the moduledoc's "The host's words".
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.
Functions
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.
The document described, for when nothing is selected: its name and description, what starts it, how to read the map, and how many steps and open slots it has.
Types
One labelled fact: a single value, or a list of them.
@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.
The options elements/6 takes; see the moduledoc's "The host's words".
@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.
Functions
@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.
@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 to read the map, and how many steps and open slots it has.