Skip to content

Fix template read-only hint/open firing over editable page content#32

Merged
DavidBabinec merged 1 commit into
mainfrom
fix/template-readonly-hint-scope
Jun 11, 2026
Merged

Fix template read-only hint/open firing over editable page content#32
DavidBabinec merged 1 commit into
mainfrom
fix/template-readonly-hint-scope

Conversation

@DavidBabinec

Copy link
Copy Markdown
Contributor

The bug

The "Part of Main template — double-click to edit" hover hint fired over the entire page — including the active page's own editable content (e.g. the ABOUT heading), not just the template chrome (header/footer). Worse, double-clicking that editable content opened the template instead of editing the node — which silently breaks inline text editing on any page that has a wrapping template.

Root cause

The active document's editable content is spliced into the wrapping template's base.outlet (CanvasComposedTree), so in the DOM it lives inside the read-only wrapper element. That wrapper carries data-instatic-readonly-* markers (it's template chrome). Both consumers resolved the region by walking straight up:

target.closest('[data-instatic-readonly-label]')   // hover hint (BreakpointFrame)
target.closest('[data-instatic-readonly-id]')      // double-click open (IframeFrameSurface)

So they found the wrapper ancestor and treated the editable page content as read-only — even though editable nodes carry their own data-node-id and never the read-only markers (the two are mutually exclusive). The "another wrapper" intuition was exactly right.

The fix

A shared closestReadonlyRegion(target) resolves the nearest boundary of either kind[data-node-id] (editable) or [data-instatic-readonly-label] (read-only). An editable node nearer than any read-only marker means the target is the active page's own content, so: no hint, no template-open. Wired into both the hover hint and the double-click-to-open, and dedups the cross-realm isElementLike helper that was copied in both files.

Tests

New closestReadonlyRegion unit tests cover the exact bug (editable node spliced inside a read-only wrapper → no region), plus read-only chrome, unmarked chrome children, plain editable nodes, and non-element targets. bun test (full), bun run build, bun run lint all green.

Verified the boundary logic via the unit tests + reading the composition path. A quick manual check in an environment with a wrapping template is worth doing: hover page content → no hint; hover header/footer → hint; double-click a page heading → inline-edit (not "open template").

🤖 Generated with Claude Code

…ge content

The 'Part of Main template — double-click to edit' hover hint fired over the
ENTIRE page (including the active page's own editable content), and
double-clicking that content opened the template instead of editing the node —
breaking inline text editing on any page with a wrapping template.

Root cause: the active document's editable content is spliced into the wrapping
template's base.outlet (CanvasComposedTree), so in the DOM it lives INSIDE the
read-only wrapper element, which carries data-instatic-readonly-* markers. Both
consumers walked straight up with closest('[data-instatic-readonly-*]'), so they
found the wrapper ancestor and treated the editable content as read-only — even
though editable nodes carry their own data-node-id and never the readonly
markers.

Fix: a shared closestReadonlyRegion(target) resolves the NEAREST boundary of
EITHER kind ([data-node-id] | [data-instatic-readonly-label]); an editable node
nearer than any readonly marker means the target is editable, so no hint / no
template-open. Wired into both the hover hint (BreakpointFrame) and the
double-click-to-open (IframeFrameSurface), and dedups the cross-realm
isElementLike helper that was copied in both files.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@DavidBabinec
DavidBabinec merged commit 5c4d146 into main Jun 11, 2026
6 checks passed
@DavidBabinec
DavidBabinec deleted the fix/template-readonly-hint-scope branch June 16, 2026 16:33
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