Skip to content

feat: let the editor fit a narrow, phone-sized container - #95

Open
alirezamhi wants to merge 1 commit into
unlayer:mainfrom
alirezamhi:feat/fit-narrow-container
Open

alirezamhi wants to merge 1 commit into
unlayer:mainfrom
alirezamhi:feat/fit-narrow-container

Conversation

@alirezamhi

Copy link
Copy Markdown

What

  • min-width: 0 on both container divs, so the editor can never stretch the page it is embedded in.
  • className and wrapperClassName on the container and the wrapper.
  • A README "Sizing and mobile" section documenting the three rules for a small screen.

Why

The component renders display: flex with a flex: 1 container, and a flex item defaults to
min-width: auto — a floor at its content's min-content width, which it refuses to shrink below.
This editor's content is far wider than any phone: the sticker and shape panels lay hundreds of
tiles out in rows that never wrap, measured at 13,634px of min-content.

In the embed's default layout that floor stays hidden, because the panel is shrink-0 with
max-width: calc(100% - 4.5rem): its width is capped by its parent, so the huge content minimum
never becomes the container's floor. But a phone has no room for a 288px panel beside the canvas, so
any mobile layout has to stack the panel. The moment it does, the panel's width comes from the
cross-axis stretch, its 13,634px minimum becomes the container's, the container becomes 13,634px
wide and the page grows a horizontal scrollbar.

Measured in this repo's own demo (pnpm --dir demo dev), 375px viewport, sticker panel open, with
only the two layout rules a phone layout needs (flex-direction: column on the panel row,
width: 100% on the panel):

container min-width container documentElement.scrollWidth
auto (current) 13,671px 13,671px
0 (this PR) 375px 375px

36 viewports wide: the tool rail is pushed off-screen and about 1 of the 8 tool icons stays
reachable. With the fix the container holds at the viewport width and the sticker rows keep their
13,634px — scrolling inside their own panel, which is how the embed already treats them.

Also: the class names

Rearranging the embed's chrome for a phone needs a breakpoint, and a breakpoint needs a selector: a
media query cannot be expressed in the style / wrapperStyle objects the component already
accepts, and inline styles cannot express one either. className / wrapperClassName are that
hook; editorId covers the id-based case.

Notes

  • min-width: 0 is written before the spread, matching the existing "flex first: a default the
    consumer's style can override" contract from the flex default — so it is not a behaviour change
    for a container already wide enough to hold the editor, and style / wrapperStyle can restore
    the previous behaviour.
  • Tests: two added (the default, and an explicit minWidth overriding it). Suite at 76 passed, and
    the 100% coverage thresholds still hold.
  • Locally green: pnpm lint, pnpm typecheck, pnpm build, pnpm test:coverage, and the demo's
    typecheck / build.

Fixes #94

A flex item defaults to `min-width: auto`, which is a floor at its content's
min-content width: it refuses to shrink below what it holds. The editor's
content is far wider than any phone — the sticker and shape panels lay
hundreds of tiles out in rows that never wrap, measured at ~13,600px of
min-content — so in a 375px viewport the container did not constrain the
editor. The editor stretched the container, the container stretched its
parent, and the page grew a horizontal scrollbar: the tool rail was pushed
off-screen and the whole UI read as zoomed in. Only ~1 of the 8 tool icons
stayed reachable.

Both the wrapper and the container now default to `min-width: 0`, so a
narrow container really does constrain the editor and those wide rows scroll
inside their own panel. `style` / `wrapperStyle` still override it, matching
the existing "flex first, a default the consumer can override" contract, so
this is not a behaviour change for a container wide enough to hold the
editor anyway.

Also add `className` and `wrapperClassName`. The editor's own chrome belongs
to the embed bundle, so the only way to rearrange it for a phone is a
breakpoint of the consumer's — and a media query cannot be expressed in the
`style` / `wrapperStyle` objects this component already accepts. The class
names are the missing hook; `editorId` remains the id-based one.

The README's new "Sizing and mobile" section states the three rules: the
wrapper never widens its parent, the container needs a definite height
(`minHeight` defaults to 500, so a full-height layout passes 0 or '100%'),
and the embed's chrome is adapted through a breakpoint.
@vercel

vercel Bot commented Oct 11, 2026

Copy link
Copy Markdown

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

A member of the Team first needs to authorize it.

@alirezamhi

Copy link
Copy Markdown
Author

Before / after at a 375px viewport, sticker panel open, captured in a real browser from this repo's demo (pnpm --dir demo dev) with only the two layout rules a phone layout needs:

min-width: auto (current) min-width: 0 (this PR)
before after
container 13,671px — the page scrolls sideways, the tool rail is pushed off-screen container 375px — the 13,634px of sticker tiles scroll inside the panel

Same harness, same run: document.documentElement.scrollWidth goes 13,671 → 375.

This branch has not been deployed

No deployments
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.

Editor stretches its container to 13,671px in a phone-sized layout (min-width: auto)

1 participant