# `MishkaCmsCoreWeb.Live.Admin.Components.RuntimePreviewModal`
[🔗](https://github.com/mishka-group/mishka_cms_core/blob/v0.0.1/lib/mishka_cms_core_web/live/admin/components/runtime_preview_modal.ex#L5)

Tabbed inspector modal for a single module-backed runtime record (Page / Component /
Layout / ErrorPage), opened from a table's "Preview" row action.

Six tabs — **Overview** (stored details + a sample metrics card), **Preview** (the
rendered output in a sandboxed `<iframe srcdoc>` with Desktop/Tablet/Mobile widths),
**Code** (raw source, copy button), **Versions** (recent AshPaperTrail versions),
**Pipeline** (the live `RuntimeStatusTimeline`), and **Configuration** (the resource's
`MishkaGervaz.Form.Web.Live` form — this modal is where a record is edited, so there is no
second form modal on the page).

Two header actions carry the record's runtime cost, and both are deliberate clicks rather than
anything the modal does by opening: **Visual Editor** leaves for the builder, and **Force compile**
builds the record's module now even when it is marked lazy (see
`MishkaCmsCoreWeb.Live.Admin.Dashboard.Runtime.PreviewHelpers.force_compile/1`). A component also
offers **Duplicate**, which writes a new component from this one and closes the modal on it (see
`MishkaCmsCoreWeb.Live.Admin.Dashboard.Runtime.PreviewHelpers.duplicate/1`).

Driven entirely by the `:preview` map that
`MishkaCmsCoreWeb.Live.Admin.Dashboard.Runtime.PreviewHelpers` maintains. The shell uses
the `runtime-preview-modal` id family so `MishkaCmsCore.CoreComponents.show_modal/1` /
`hide_modal/1` drive it, like the form modal.

See `MishkaCmsCore.Runtime.RuntimePreview` (renders the iframe document + Overview rows).

## No `style` attribute

This modal renders in the admin document, which is served the compiled `admin.css`, so every rule
here is a Tailwind class and a Content-Security-Policy can drop `style-src-attr 'unsafe-inline'` —
it has no nonce to offer an attribute. The two values that vary are written as whole literal
classes, one function clause each, because Tailwind reads SOURCE TEXT and a class with an
interpolation hole gets no rule at all: `device_class/1` sizes the preview frame (in step with
`MishkaCmsCore.Runtime.RuntimePreview.device_width/1`) and `bar_height_class/1` draws the four
priority bars.

The document INSIDE the frame is a separate matter — see `RuntimePreview`, which styles its own
chrome with a `<style>` element because a class of ours reaches nothing in there. That element is
nonced: `srcdoc` inherits the ADMIN policy of the page framing it, so an unnonced one is refused
and the preview renders bare. The nonce is not this component's to pass, though — the modal only
hands the finished `@html` / `@edit_html` to the frame, and
`MishkaCmsCoreWeb.Live.Admin.Dashboard.Runtime.PreviewHelpers`, which builds those strings, reads
`socket.assigns[:csp_nonce]` off the LiveView that renders this modal.

# `modal`

## Attributes

* `preview` (`:map`) (required)

---

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