# `PhoenixKit.Install.StatusTree`
[🔗](https://github.com/BeamLabEU/phoenix_kit/blob/v2.13.7/lib/phoenix_kit/install/status_tree.ex#L1)

Renders the box-drawing tree `mix phoenix_kit.status` and
`mix phoenix_kit.update` print.

Extracted from the status task so the layout can be unit tested. It used to
be a private function that wrote straight to `IO.puts/1`, which meant the
only way to check a change was to run the task against a live database —
so in practice nobody checked.

`render/1` returns a string and touches no IO; the caller prints it.

## Rows

A row is `{label, value}` or `{label, value, children}`. Children render as
an indented sub-tree, which is how per-module schema versions hang off the
"Modules" row:

    iex> PhoenixKit.Install.StatusTree.render([
    ...>   {"Installed", "V159"},
    ...>   {"Modules", "2 modules", ["Boards: V01", "Inbox: V01 → V02"]},
    ...>   {"Next", "Ready"}
    ...> ])
    "├── Installed: V159\n" <>
    "├── Modules: 2 modules\n" <>
    "│   ├── Boards: V01\n" <>
    "│   └── Inbox: V01 → V02\n" <>
    "└── Next: Ready"

# `row`

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

# `render`

```elixir
@spec render(
  [row()],
  keyword()
) :: String.t()
```

Renders rows as a tree. Returns a string with no trailing newline.

`:label_format` is an optional 1-arity function applied to each label —
the tasks pass one that wraps labels in ANSI bold. Kept out of the layout
itself so tests can assert on plain text.

---

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