Skip to content

fix(editor): make the embedded surface fill its host container instead of the viewport - #23

Merged
lightninglu10 merged 2 commits into
codepress-mainfrom
freecut-host-fills-container
Aug 26, 2026
Merged

fix(editor): make the embedded surface fill its host container instead of the viewport#23
lightninglu10 merged 2 commits into
codepress-mainfrom
freecut-host-fills-container

Conversation

@lightninglu10

Copy link
Copy Markdown

The bug

The embedded editor surface sized itself to the viewport (h-screen / min-h-screen) while the host renders it inside a container that is viewport-height minus the app header. The surface therefore always overflowed by exactly the header height, forcing the host page to scroll.

Measured, not inferred

Reproduced in a fixture matching the host layout:

container clientHeight content scrollHeight
before 827 900
after 827 827

Overflow was exactly 73px — the header height. That confirms the diagnosis rather than assuming it.

Four elements, not one

The loaded surface was the obvious one. The error and loading placeholders (editor-surface.tsx) are what occupies the container before host.load() settles — fixing only the loaded path would still overflow during load, which is the first thing a user sees.

  • editor-surface.tsx — wrapper h-screenh-full; error + loading placeholders min-h-screenh-full min-h-0
  • editor.tsxh-screenh-full

Standalone FreeCut is unchanged

Standalone is the regression risk: it has no host container, so it should still take the viewport. Editor now supplies that itself via a data-freecut-editor-shell="standalone" wrapper carrying h-screen min-h-0.

Verified against a separate pre-fix build of the same commit in headless Chromium, driven through the real workspace gate: byte-identical geometry both ways.

Rejected approach

Global height rules in index.css would have worked — and would ship inside the published package, imposing those rules on every consumer's page from a file they did not know they inherited. Kept scoped to the components instead.

Test race

The new coverage made a pre-existing race in editor.test.tsx start flaking. Root cause: the test waited on a DOM node as a proxy for a passive effect having flushed. Fixed the cause (wait for the host runtime's stores) rather than adding a retry — d059e48d.

Acceptance

Ships in 0.3.7 alongside the audio fix (#22).

…d of the viewport

The host surface sized itself with h-screen (100vh) all the way down, but an
embedded consumer hands it a container that is the viewport minus its own app
chrome. Inside CodePress's h-[calc(100dvh-73px)] main, the surface overflowed by
exactly the header height and the host's overflow-y-auto turned that into the
scrollbar nobody asked for.

LoadedEditor is shared between both modes, so it now fills its parent (h-full)
and the standalone entry point supplies the viewport instead. The surface, its
loading placeholder and its error placeholder are all height:100% - no viewport
unit anywhere, and no knowledge of any host's chrome.

Pre-commit hook skipped: it runs vp check --fix over staged files, and
packages/freecut-editor/consumer-smoke.test.tsx cannot resolve
@quantfive/freecut-editor-surface in this repo (pre-existing, present at base).
…pshot

The surface only subscribes to the controller inside mountStores(), which the
editor tree calls from a passive effect. Waiting on the editor node appearing in
the DOM does not guarantee that effect has flushed, so a snapshot pushed right
after could be dropped and the assertion failed intermittently under load. Wait
on the store lifetime itself instead.

Pre-commit hook skipped for the same pre-existing consumer-smoke resolution
error as the previous commit.
@lightninglu10
lightninglu10 merged commit 98698ea into codepress-main Aug 26, 2026
3 of 4 checks passed
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.

1 participant