Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions content/blocks/preview.md
Original file line number Diff line number Diff line change
Expand Up @@ -399,9 +399,9 @@ See the [window preview example](https://github.com/gethinode/mod-blocks/blob/v2

### Window states and appearance

The window title bar shows `Preview` before its current view is admitted, `Loading` while it waits, `Live` after the current view passes its configured readiness check, and `Unavailable` when a wait times out. Without `ready_message`, the iframe load event ends the wait; with it, the current frame must post that exact message. Theme synchronization adds a matching current-theme acknowledgement before `Live`. In a compact title bar, a shorter visible state such as `Wait` or `Error` sits beside the open action; the full accessible status remains available.
The window title bar shows `Preview` before its current view is admitted, `Loading` while it waits (a re-proof of a ready view keeps `Live`, see below), `Live` after the current view passes its configured readiness check, and `Unavailable` when a wait times out. Without `ready_message`, the iframe load event ends the wait; with it, the current frame must post that exact message. Theme synchronization adds a matching current-theme acknowledgement before `Live`. In a compact title bar, a shorter visible state such as `Wait` or `Error` sits beside the open action; the full accessible status remains available.

While a view is loading or has failed, a 30% black scrim sits over its poster, with the status and spinner painted above the scrim. A ready view removes the poster and scrim. A static phone view stays in `Preview` without a loading spinner or scrim because it makes no embedded-page request.
While a view is loading or has failed, a 30% black scrim sits over its poster, with the status and spinner painted above the scrim. A ready view removes the poster and scrim, and from mod-blocks v2.13.1 a ready view that re-proves a new document or theme keeps them removed. A static phone view stays in `Preview` without a loading spinner or scrim because it makes no embedded-page request.

The window open action uses the theme's existing `externalLink` icon mapping, whose default is a generic external-link glyph. The window's CSS custom property `--preview-window-border-radius` overrides the Sass fallback `$preview-window-border-radius` (default `0.375rem`) without changing other theme corners. A site can set the custom property, for example to `0`, to choose square window corners.

Expand All @@ -426,11 +426,11 @@ theme_message: example:theme

When adapting the snippet to your own site, use a child page your site serves instead of `/preview-demo/ready/`.

After the current child sends its readiness message, the parent requests the resolved theme with a unique positive safe-integer request ID, for example `{type: "example:theme", theme: "dark", requestId: 1}`. The parent sends only to that frame's captured nonopaque HTTP(S) origin. The child validates the message from its actual parent and exact parent origin, applies the requested theme, then replies with the same fields and `applied: true`. The parent reveals the view only after an acknowledgement from the current frame window at its captured origin matches the request ID and theme. A new child document or theme request needs a fresh matching acknowledgement; an old or out-of-order reply cannot reveal the view. The parent resolves `auto` to light or dark before sending the request.
After the current child sends its readiness message, the parent requests the resolved theme with a unique positive safe-integer request ID, for example `{type: "example:theme", theme: "dark", requestId: 1}`. The parent sends only to that frame's captured nonopaque HTTP(S) origin. The child validates the message from its actual parent and exact parent origin, applies the requested theme, then replies with the same fields and `applied: true`. For the first reveal of an activation, the parent reveals the view only after an acknowledgement from the current frame window at its captured origin matches the request ID and theme. A new child document or theme request needs a fresh matching acknowledgement; an old or out-of-order reply cannot reveal the view. A view that was already ready re-proves in place instead, as described below. The parent resolves `auto` to light or dark before sending the request.

For full-document navigation, the bridge carries transient theme intent in a `window.name` seed beginning `hinode-preview-theme:` followed by `{type, theme, requestId, parentOrigin}` JSON. The initial seed uses request ID `0`; theme requests use positive safe integers. Keep the complete seed within 512 JavaScript string code units and use a canonical HTTP(S) parent origin. A participating child reads the seed as early theme context and mirrors each validated request into its own `window.name` before acknowledging; the seed alone is not readiness or proof that the theme was applied. This context is not a cookie or stored preference.

On `pagehide` and early startup of a newly navigated document, a participating child sends a matching `applied: false` invalidation. The parent also invalidates the current theme proof on the iframe's load event. A current invalidation returns the frame to its poster/waiting state, makes it inert, and requires a fresh readiness message, theme request, and `applied: true` acknowledgement before it appears again. Signals from an older document or superseded request cannot invalidate newer proof.
On `pagehide` and early startup of a newly navigated document, a participating child sends a matching `applied: false` invalidation. The parent also invalidates the current theme proof on the iframe's load event. A current invalidation requires a fresh readiness message, theme request, and `applied: true` acknowledgement before the view counts as ready again. From mod-blocks v2.13.1, a view that was already ready in its current activation re-proves in place: its frame stays shown and not inert, its poster stays hidden, the pane is busy, and a window's title bar keeps its ready state (`Live`) without a new status announcement until the acknowledgement arrives. A new outer theme re-proves the same way. The first wait of an activation, and any wait after a failure, still returns the frame to its poster and makes it inert, and the deadline still fails a re-proof with the poster and alert and an inert, hidden frame. A late acknowledgement from the current frame still recovers. Earlier releases show the poster again on every such invalidation and theme change. Signals from an older document or superseded request cannot invalidate newer proof.

Hinode also exposes the synchronous, cancelable document event `hinode:color-mode:before-change` (Hinode v3.45.0 or later). Its `detail.theme` is the requested preference (`auto`, `light`, or `dark`); invalid values normalize to `auto`. When not canceled, `auto` resolves to system appearance after dispatch. Calling `preventDefault()` skips that setter's preference storage, root theme attributes, and selector updates, but does not undo earlier preference reads/writes or native control changes. Without cancellation, normal theme behavior remains. Hinode provides only this event; it does not manage a framed child's theme selector. A cooperating child page managed by its preview parent may cancel this event to intercept local setter updates while managed, then apply the parent's resolved theme without persisting it. The child may also hide its own duplicate theme selector while managed so the outer page remains authoritative, and keep its normal selector behavior when standalone or unmanaged.

Expand Down Expand Up @@ -475,7 +475,7 @@ The active view loads by default; views load when first shown. `activation: clic

The iframe `load` event does not prove the target is healthy: browsers can fire it for an HTTP 503 response or a refused connection. With the default empty `ready_message`, load ends the wait. To wait for positive readiness, set `ready_message` to a token shared with a cooperating framed page. For example, the self-contained [readiness example](https://github.com/gethinode/mod-blocks/blob/v2.13.0/exampleSite/content/components/preview-ready.md) uses `example:ready`. A child page can announce readiness after its DOM is ready and answer only requests from its own parent that contain the matching token. The preview requests a reply when the frame loads, so an early announcement can be recovered. The example's Ready page replies; its Silent page does not.

When a live view loads in readiness mode, it stays busy behind its poster and its frame cannot take focus until the current frame acknowledges the exact token. If the deadline expires first, the frame is hidden and stays inert, so it still cannot take focus. With click activation, before the poster button is pressed, item changes update the selected poster and item heading, when supplied, without requesting a frame or starting a wait. After activation, each item or device navigation gets its own wait. A late acknowledgement from the current frame can recover the view. Messages from another frame, a previous navigation, or with a different token do not count. This is a one-time navigation check, not ongoing health monitoring; behavior after the framed app navigates internally belongs to that app. Keep the token non-sensitive: messages must not carry visitor data, privileged actions, URLs, or HTML.
When a live view loads in readiness mode, it stays busy behind its poster and its frame cannot take focus until the current frame acknowledges the exact token. If the deadline expires first, the frame is hidden and stays inert, so it still cannot take focus. With click activation, before the poster button is pressed, item changes update the selected poster and item heading, when supplied, without requesting a frame or starting a wait. After activation, each item or device navigation gets its own wait. A late acknowledgement from the current frame can recover the view. Messages from another frame, a previous navigation, or with a different token do not count. This is a one-time navigation check, not ongoing health monitoring; without `theme_message`, behavior after the framed app navigates internally belongs to that app. With `theme_message` (mod-blocks v2.13.1 or later), each new document of a ready view re-proves as described under [Synchronize an embedded page's theme](#synchronize-an-embedded-pages-theme). Keep the token non-sensitive: messages must not carry visitor data, privileged actions, URLs, or HTML.

The build-time fallback remains distinct from runtime failure: a block that shows its fallback has no waiting or failed runtime state. [Embedding restrictions](#embedding-restrictions) describes when the build-time checks run and how a failed request is handled.

Expand Down
Loading