Skip to main content
Light Dark System

Preview Frame

<zn-preview-frame> | ZnPreviewFrame
Since 1.0 experimental

Embeds a live preview iframe and drives the hp-preview postMessage protocol: answers the frame’s ready handshake with a config payload fetched from data-uri, auto-saves watched forms on change, and refreshes the preview after each save.

The frame loads the embed page from src, waits for it to post hp-preview:ready, fetches the JSON payload from data-uri and posts it back into the frame as hp-preview:config. The embed then reports hp-preview:rendered or hp-preview:error.

The example below embeds the demo embed page, which implements the embed side of the protocol. frame-origin must match the embed’s origin exactly — messages from any other origin are ignored — so the example sets it at runtime since the docs demo is same-origin.

<zn-preview-frame
  id="preview-frame-demo"
  src="/components/preview-frame-demo/"
  data-uri="/data/preview-frame-payload.json"
  watch="#preview-frame-demo-form"></zn-preview-frame>

<script>
  document.getElementById('preview-frame-demo').frameOrigin = location.origin;
</script>

The frame always fills the panel; zoom (0–1, default 1) zooms the previewed page out browser-style — e.g. zoom="0.4" renders the content at 40% size with correspondingly more of the page visible. min-height (default 480) sets the visible panel height in pixels.

Live Form Updates

In a real deployment, editing a watched form auto-saves it and the preview refreshes with the newly saved config. This docs site is static, so the example simulates the save: form changes are encoded into a data: payload URI and refresh() re-runs the fetch → hp-preview:config cycle — the same path a real save triggers.

<form id="preview-frame-live-form" class="preview-frame-live-form">
  <zn-input name="merchant" label="Merchant" value="Acme Donuts"></zn-input>
  <zn-input name="amount" label="Amount" value="£24.99"></zn-input>
  <zn-input name="buttonLabel" label="Button label" value="Pay £24.99"></zn-input>
  <label class="preview-frame-live-form__color">Accent
    <input type="color" name="accent" value="#6936f5">
  </label>
</form>

<zn-preview-frame
  id="preview-frame-live"
  src="/components/preview-frame-demo/"
  watch="#preview-frame-live-none"></zn-preview-frame>

<script>
  customElements.whenDefined('zn-preview-frame').then(() => {
    const frame = document.getElementById('preview-frame-live');
    const form = document.getElementById('preview-frame-live-form');
    frame.frameOrigin = location.origin;

    const update = () => {
      const payload = Object.fromEntries(new FormData(form));
      frame.dataUri = 'data:application/json,' + encodeURIComponent(JSON.stringify(payload));
      frame.refresh();
    };

    form.addEventListener('zn-input', update);
    form.addEventListener('input', update);
    update();
  });
</script>

<style>
  .preview-frame-live-form {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    align-items: flex-end;
    margin-bottom: 16px;
  }

  .preview-frame-live-form zn-input {
    flex: 1;
    min-width: 140px;
  }

  .preview-frame-live-form__color {
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 0.875rem;
    font-weight: 500;
  }
</style>

Error Overlay

When the embed reports hp-preview:error (or fetching the payload fails), the message is shown in an overlay and zn-error is emitted. This example uses a payload that asks the demo embed to fail.

<zn-preview-frame
  id="preview-frame-demo-error"
  src="/components/preview-frame-demo/"
  data-uri="/data/preview-frame-payload-error.json"
  watch="#preview-frame-demo-error-form"></zn-preview-frame>

<script>
  document.getElementById('preview-frame-demo-error').frameOrigin = location.origin;
</script>

Importing

If you’re using the autoloader or the traditional loader, you can ignore this section. Otherwise, feel free to use any of the following snippets to cherry pick this component.

To import this component from the CDN using a script tag:

<script type="module" src="https://cdn.jsdelivr.net/npm/@kubex/zinc@1.1.62/dist/components/preview-frame/preview-frame.js"></script>

To import this component from the CDN using a JavaScript import:

import 'https://cdn.jsdelivr.net/npm/@kubex/zinc@1.1.62/dist/components/preview-frame/preview-frame.js';

To import this component using a bundler:

import '@kubex/zinc/dist/components/preview-frame/preview-frame.js';

Properties

Name Description Reflects Type Default
src URL of the preview shell page (tokened embed URL). string ''
frameOrigin
frame-origin
Expected origin of the iframe; all postMessage traffic is checked against it. string ''
dataUri
data-uri
Endpoint returning the hp-preview:config payload JSON. The console proxy rewrites this attribute to an app-prefixed path for proper fetch resolution. string ''
watch Selector (resolved against the component’s root node) for the forms to watch. Defaults to only forms explicitly opted in via a data-auto-save attribute — unmarked forms keep normal submit behavior and are never intercepted, auto-saved, or used to trigger a preview refresh. Override to widen the scope. string 'form[data-auto-save]'
debounce Debounce in ms between a form change and its auto-save. number 400
zoom Zooms the previewed page out (0–1]. The frame always fills the panel; zoom shrinks the content browser-style, so 0.4 shows the page at 40% size with correspondingly more of it visible. 1 = natural size. number 1
minHeight
min-height
The visible height (in CSS pixels) of the preview panel. Fixed rather than measured, because a measured height would feed back into the scaled iframe’s layout box and grow unbounded. number 480
updateComplete A read-only promise that resolves when the component has finished updating.

Learn more about attributes and properties.

Events

Name React Event Description Event Detail
zn-error Emitted when the preview reports a render error or a save fails. -

Learn more about events.

Methods

Name Description Arguments
refresh() Re-fetches the payload and pushes a fresh config to the preview. -

Learn more about methods.

Parts

Name Description
base The component’s base wrapper.
iframe The preview iframe.
error The error overlay.

Learn more about customizing CSS parts.