Skip to content

feat: add a placeholder slot for the embed loading gap - #58

Open
sidgaikwad wants to merge 1 commit into
unlayer:mainfrom
sidgaikwad:feat/loading-placeholder
Open

feat: add a placeholder slot for the embed loading gap#58
sidgaikwad wants to merge 1 commit into
unlayer:mainfrom
sidgaikwad:feat/loading-placeholder

Conversation

@sidgaikwad

Copy link
Copy Markdown
Contributor

Fixes #37.

Problem

Between mount and the editor being ready, the component rendered an empty container. On a cold CDN cache that's the full embed.js request plus the versioned-bundle hop showing as a blank box at minHeight: 500.

There was no supported way to fill it: onLoad only fires after success, so consumers had to render their own absolutely-positioned overlay from first paint, tear it down in onLoad, know about the internal two-div layout — and it still didn't cover the failure path.

Change

<ImageEditor image={url} placeholder={<Spinner />} />

Two design decisions worth your attention:

  • It's an overlay sibling, not a child of the mount container. The embed owns that container's DOM (it renders div.image-editor-root into it), so React must not reconcile children in and out from under it.
  • It stays visible when the mount fails. The issue flagged this as an open question. A failed load ending on a blank box is the worst outcome, so the placeholder persists and consumers pair it with onError to swap in a failure message. Documented in the README and the prop's doc comment.

position: relative is applied to the wrapper only while a placeholder is actually showing, so existing layouts are untouched.

Verification

Beyond the unit tests, I wired it into the demo and pointed scriptUrl at a non-existent file to hold the failure state open.

Before — embed fails to load, entire editor area is blank white:

status bar reads Error: Failed to load the image editor embed script: .../DOES-NOT-EXIST.js, content area completely empty

After — same failure, with a spinner and "Loading the image editor…" centred in the area.

The demo scaffolding was reverted; this PR touches only src/, test/ and the README.

  • 4 new tests (shown until mount, absent when the prop is, survives a failed mount, returns during a remount)
  • 50 tests; coverage still 100% statements / branches / functions / lines
  • lint, typecheck, build clean

Conflict note

Touches the same render block as #55, and the same README props table as #54.

Between mount and the editor being ready the component rendered an empty
container. On a cold CDN cache that is the full embed.js request plus the
versioned-bundle hop showing as a blank box at minHeight 500, with no
supported way to fill it: onLoad only fires after success, so consumers
had to overlay their own absolutely-positioned spinner and know about the
internal two-div layout.

Render `placeholder` centred over the container while the editor is null.

Two design points:

- It is an overlay sibling, not a child of the mount container. The embed
  owns that container's DOM and React must not reconcile children in and
  out from under it.
- It stays visible when the mount fails, so a failed load never ends on a
  blank box. Consumers pair it with onError to swap in a failure message.

position: relative is only applied when a placeholder is actually being
shown, so existing layouts are untouched.
@vercel

vercel Bot commented Sep 4, 2026

Copy link
Copy Markdown

@sidgaikwad is attempting to deploy a commit to the Unlayer Team on Vercel.

A member of the Team first needs to authorize it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a loading/placeholder slot — the container is blank while the embed loads

1 participant