Skip to content

fix(studio): a text edit saves to the element that was edited, or says why it could not - #4803

Merged
miguel-heygen merged 2 commits into
mainfrom
fix/studio-text-edit
Oct 1, 2026
Merged

miguel-heygen merged 2 commits into
mainfrom
fix/studio-text-edit

Conversation

@miguel-heygen

@miguel-heygen miguel-heygen commented Sep 30, 2026 •

Copy link
Copy Markdown
Collaborator

What

A text edit made in place on the Studio canvas is now saved to the element that was edited, whatever is selected when the edit closes. When a text edit cannot be saved, Studio says so in an error toast, logs why, and puts the old text back, so the screen never shows text that is not in the file.

Why

Today the in-place text commit saves against the current selection, and silently drops the edit when the edited element is not that selection. The typed text stays on screen, nothing is written, no toast appears, and the text is gone after a reload.

Repro on main (built Studio via hyperframes preview): double-press a headline and type. While the edit is open, something else changes the selection (an agent calls studio_select on another element, or a host app clears its pick). Press Enter: nothing is written in 8 s, no toast, and a reload shows the old text. A host that opens the edit on a child of what it has selected (a composition host or a container) hits the same path, and so does a host whose Escape clears the pick before the edit closes.

How

  • handleDomRichTextCommit resolves the selection from the edited element itself (buildDomSelectionFromTarget(element, { exactTarget: true, skipSourceProbe: true })), so the patch targets that element's own source file (a nested element saves to its sub-composition file).
  • The three silent returns are gone. Each refusal (the preview reloaded under the edit, the element is not in the source, the element cannot be edited in place) shows an error toast, logs with console.error, and puts the previous markup back.
  • The read-only refusal is unchanged (quiet, old text back).
  • After a save, Studio refreshes the selection only when the edited element is still what is selected. If the selection moved on (or a host cleared it) while the edit was open, it is left as it is, so a following Delete or move never picks up the edited text by surprise.

Test plan

  • Unit tests: useDomEditTextCommits.test.tsx (the selection is another element, or none: the edit saves to the edited element and the selection is left unchanged; the edited element still selected: the selection is refreshed; an unresolvable element: toast, console error, old text back) and useDomEditCommits.test.tsx (a commit onto a removed preview node is refused and now says so). The new tests fail on main's source; breaking the selection condition either way turns one of them red.

  • Studio unit tests for src/hooks and src/components/editor: 1662 passed. tsc --noEmit clean.

  • Manual: headless Chrome on a built CLI preview, root and nested text: double-press, type, Enter writes in about 100 to 170 ms (unchanged); the agent-select repro above writes on the branch and not on main.

  • Edit accuracy bench, text cases (from the open bench PR that adds them), same machine, same main, 2 jobs:

    Build textedit root textedit nested textselect root textselect nested text metric
    main pass pass pass pass 4/4
    this branch pass pass pass pass 4/4

    All four fail only smooth on both builds (a loaded Linux box; the blank-page control drops frames there too). The bench's text route keeps the selection on the edited element, so it passes on main; the repro above is the route it does not cover.

  • Documentation updated (if applicable)

  • Comments follow CONTRIBUTING.md "Comments"

Before

On main: the headline was double-pressed and " typed" entered; an agent then selected the card, and Enter was pressed. The typed text stays on screen, nothing is written and no toast appears:

Before: after Enter, typed text shown but not saved

After a reload the typed text is gone:

Before: after reload, the typed text is lost

After

Same steps on this branch. The file is written on Enter, the card stays the only selected element, and after a reload the typed text is still there:

After: after reload, the typed text is kept

@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown

Edit accuracy: 434 passing here, 434 on the base branch

The gate passes.
Smoothness is reported in the artifact, not gated. A case fails only if it fails 2 of 3 runs.

@miguel-heygen
miguel-heygen marked this pull request as ready for review October 1, 2026 00:40
@miguel-heygen
miguel-heygen added this pull request to the merge queue Oct 1, 2026
Merged via the queue into main with commit c777f36 Oct 1, 2026
151 of 153 checks passed
@miguel-heygen
miguel-heygen deleted the fix/studio-text-edit branch October 1, 2026 01:02
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.

2 participants