# `MishkaCmsCoreWeb.Templates.SnippetForm`
[🔗](https://github.com/mishka-group/mishka_cms_core/blob/v0.0.1/lib/mishka_cms_core_web/templates/snippet_form.ex#L5)

A MishkaGervaz custom form template: the "Save as snippet" box at the top of the Studio's Snippets
tab.

It owns the whole box and nothing below it — the saved list is a Gervaz TABLE,
`MishkaCmsCoreWeb.Templates.StudioSnippets`.

## The scope control is the point

Before this, scope was decided FOR the author: a node selected saved `:page`, nothing selected
saved `:shared`, and there was no way to say otherwise. The three radios here are that choice made
explicit, in the same chip idiom as the list's own filter chips.

They are radios rather than buttons so the browser holds the selection: no `phx-change` round trip
per click, which also means clicking one cannot disturb a half-typed name. The selected styling is
`peer-checked:`, so it is CSS rather than a re-render.

What each one means, and why `visibility` is not simply the stored `scope`:

| Radio      | `scope`   | `site_id`        | Who sees the snippet          |
|------------|-----------|------------------|-------------------------------|
| This page  | `:page`   | this site        | only this document's editor   |
| Shared     | `:shared` | this site        | every editor on this site     |
| All sites  | `:shared` | `nil`            | every editor on every site    |

"All sites" is a `site_id` decision, not a `scope` one — which is why the radio posts a
`visibility` param that `MishkaCmsCore.Runtime.Snippet`'s `before_save` hook translates, rather
than posting `scope` directly. It is offered to a master only: a tenant's `:create` action forces
`site_id` to its own tenant, so showing the choice would be a promise the action cannot keep.

## The markup the source rides in on

`source` — the serialised subtree, recomputed on every canvas edit — is NOT a form field. It
reaches the action through a hidden input that `Panels` renders OUTSIDE this component and
associates with `form="pb-snippet-form"`; `FormData` collects form-associated controls wherever
they sit in the DOM, so LiveView serialises it with the rest. Passing it through the component's
`defaults` instead would rebuild the form on every keystroke-adjacent edit and wipe the name the
author was typing.

# `render_field`

# `render_group`

# `render_step_indicator`

---

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