Skip to content

Forms: classic editor pick-existing-form modal with inline ref preview#48082

Open
enejb wants to merge 1 commit intotrunkfrom
fix/classic-editor-cfm-modal
Open

Forms: classic editor pick-existing-form modal with inline ref preview#48082
enejb wants to merge 1 commit intotrunkfrom
fix/classic-editor-cfm-modal

Conversation

@enejb
Copy link
Copy Markdown
Member

@enejb enejb commented Apr 14, 2026

Fixes FORMS-642

Proposed changes

  • Classic Editor: replace the default "Add Contact Form" media button, TinyMCE toolbar button, and Text-editor "contact form" quicktag so they all open a new modal instead of scaffolding a raw [contact-form]…[/contact-form] shortcode inline.
  • The modal lets the user pick from their existing jetpack_form posts (fetched via /wp/v2/jetpack-forms), previews the selected form in an iframe, and inserts a [contact-form ref="{id}"] shortcode on confirm.
  • Empty state in the modal links to wp-admin/post-new.php?post_type=jetpack_form so users create new forms in the real forms editor.
  • Inline [contact-form ref="{id}"] references now render the real form in the TinyMCE view via an iframe loading the existing preview URL with a new &bare=1 mode that strips theme chrome but keeps all block/theme CSS. The pencil on a ref-based preview opens the form editor (wp-admin/post.php?post={id}&action=edit) in a new tab.
  • Gated on the central-form-management feature flag: when CFM is disabled, no button is registered — the legacy inline shortcode editor for existing [contact-form][contact-field …] content is left completely untouched so older sites keep working.

Modal: Form picker

Screenshot 2026-04-13 at 9 06 44 PM

Form in the editor is a preview of the form. You can click the little pencil which takes you to the form editor for that form.

Screenshot 2026-04-13 at 9 07 06 PM

Related product discussion/links

Does this pull request change what data or activity we track or use?

No — reuses the existing preview nonce + edit_post capability check for the bare-preview query.

Testing instructions

Setup

  1. Activate the Classic Editor plugin on a site with Jetpack Forms and CFM enabled (default since Forms: Enable Central Forms Management by default for all sites #47826).
  2. Have at least one jetpack_form post published via the Forms dashboard (or create one from the modal's empty state).
  3. Open a post/page for editing in the classic editor.

Primary path — new insertion flow

  1. Click Add Contact Form (media button). The new modal opens with:
    • a "Choose a form…" dropdown listing your saved forms (most-recently-modified first),
    • a preview iframe that shows the real form when one is selected,
    • a "Create a new form" button that opens post-new.php?post_type=jetpack_form in a new tab.
  2. Select a form → the iframe loads a clean preview (no theme header/footer).
  3. Click Insert form[contact-form ref="{id}"] lands in the editor. The inline TinyMCE preview should render the real form (fields + submit button). Publish and view on the frontend to confirm the form renders.
  4. Repeat via the TinyMCE toolbar form button (same modal).
  5. Switch to Code view, click the contact form quicktag → same modal opens; inserting uses QTags.insertContent.
  6. With the modal open, verify Escape, clicking the overlay, clicking Cancel, and clicking the ✕ all close it without inserting. Focus returns to the button that opened it.

Ref-based inline preview

  1. With a [contact-form ref="{id}"] in the post, switch to Visual mode. The TinyMCE view should show the full form rendered inline, not a generic placeholder.
  2. Click the pencil on the view → opens post.php?post={id}&action=edit in a new tab; the view exits edit mode cleanly in the post.

Legacy behavior preserved

  1. In a post containing a legacy [contact-form]…[contact-field …]…[/contact-form] (no ref), the inline field editor (pencil) should still work exactly as before — add/remove/reorder fields in the iframe editor.

CFM disabled

  1. Add add_filter( 'jetpack_forms_alpha', '__return_false' ); via an mu-plugin (or equivalent). Reload the editor. The Add Contact Form media button, TinyMCE toolbar button, and quicktag should all be absent; the legacy inline editor for existing shortcodes continues to work.

Empty state

  1. Trash all jetpack_form posts, open the modal → empty state with Create a new form button linking to post-new.php?post_type=jetpack_form. No insert button is shown.

Cross-browser

  1. Chrome and Firefox both show the preview iframe at full editor width with the image-select / rating / file field blocks rendered correctly.

…g-form modal

Classic Editor now opens a modal that lets users pick an already-saved
jetpack_form post and insert a [contact-form ref="{id}"] shortcode
instead of scaffolding a fresh shortcode inline. Inserted references
preview the real form in an iframe via the existing preview URL (new
bare=1 mode strips theme chrome). The pencil on a ref-based preview
opens the form in its own editor. The media button, TinyMCE toolbar
button, and text-editor quicktag all route through the same modal.

Gated on the central-form-management feature flag — the buttons are
not registered at all when CFM is disabled. The legacy inline field
editor for already-present [contact-form][contact-field] shortcodes
is untouched.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@enejb enejb added [Status] Needs Review This PR is ready for review. [Feature] Contact Form labels Apr 14, 2026
@enejb enejb self-assigned this Apr 14, 2026
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 14, 2026

Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.

  • To test on WoA, go to the Plugins menu on a WoA dev site. Click on the "Upload" button and follow the upgrade flow to be able to upload, install, and activate the Jetpack Beta plugin. Once the plugin is active, go to Jetpack > Jetpack Beta, select your plugin (Jetpack), and enable the fix/classic-editor-cfm-modal branch.
  • To test on Simple, run the following command on your sandbox:
bin/jetpack-downloader test jetpack fix/classic-editor-cfm-modal

Interested in more tips and information?

  • In your local development environment, use the jetpack rsync command to sync your changes to a WoA dev blog.
  • Read more about our development workflow here: PCYsg-eg0-p2
  • Figure out when your changes will be shipped to customers here: PCYsg-eg5-p2

@github-actions
Copy link
Copy Markdown
Contributor

Thank you for your PR!

When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:

  • ✅ Include a description of your PR changes.
  • ✅ Add a "[Status]" label (In Progress, Needs Review, ...).
  • ✅ Add testing instructions.
  • ✅ Specify whether this PR includes any changes to data or privacy.
  • ✅ Add changelog entries to affected projects

This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖


Follow this PR Review Process:

  1. Ensure all required checks appearing at the bottom of this PR are passing.
  2. Make sure to test your changes on all platforms that it applies to. You're responsible for the quality of the code you ship.
  3. You can use GitHub's Reviewers functionality to request a review.
  4. When it's reviewed and merged, you will be pinged in Slack to deploy the changes to WordPress.com simple once the build is done.

If you have questions about anything, reach out in #jetpack-developers for guidance!

@jp-launch-control
Copy link
Copy Markdown

Code Coverage Summary

Coverage changed in 4 files.

File Coverage Δ% Δ Uncovered
projects/packages/forms/src/contact-form/js/editor-view.js 0/309 (0.00%) 0.00% 191 💔
projects/packages/forms/src/contact-form/class-form-preview.php 32/214 (14.95%) -8.58% 78 💔
projects/packages/forms/src/contact-form/class-editor-view.php 100/195 (51.28%) -12.82% 39 💔
projects/packages/forms/src/contact-form/js/tinymce-plugin-form-button.js 0/8 (0.00%) 0.00% -2 💚

Full summary · PHP report · JS report

If appropriate, add one of these labels to override the failing coverage check: Covered by non-unit tests Use to ignore the Code coverage requirement check when E2Es or other non-unit tests cover the code Coverage tests to be added later Use to ignore the Code coverage requirement check when tests will be added in a follow-up PR I don't care about code coverage for this PR Use this label to ignore the check for insufficient code coveage.

@simison simison requested a review from ilonagl April 14, 2026 09:17
@enejb enejb requested a review from a team April 14, 2026 12:41
font: 18px/1 dashicons;
}

/* Pick-existing-form modal (classic editor). */
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of so much custom CSS to re-create a new modal, could we use Thickbox instead? Much of the core functionality (plugins page for example) uses it as well for basic modals.

body.jetpack-form-bare-preview input,
body.jetpack-form-bare-preview textarea,
body.jetpack-form-bare-preview select,
body.jetpack-form-bare-preview button {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Surprised not to have a tag here but seemed to not be possible to click links anyway.

If the whole iframe is disabled for interactions are these needed?

</select>
</label>
<a class="button grunion-form-picker-new" href="{{ data.new_form_url }}" target="_blank" rel="noopener noreferrer">
{{ data.labels.picker_new_form }}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should indicate in the button that it opens in a new tab, or decide to open it in the same tab.

@simison
Copy link
Copy Markdown
Member

simison commented Apr 14, 2026

Some bugs:

File upload banner renders in preview oddly:
Screenshot 2026-04-14 at 16 04 11

Inconsistent copy for CTA/header/save:
Screenshot 2026-04-14 at 16 02 37

Slider and phone number field looked broken — there could be new future fields which end up looking the same so might need a generic solution?
Screenshot 2026-04-14 at 16 01 56

Iframe container is missing corners:
Screenshot 2026-04-14 at 16 02 04

Ideally this button would alert somehow it's gonna open a new tab, or we open in current tab instead:
image

body.jetpack-form-bare-preview .wp-block-button__link,
body.jetpack-form-bare-preview .wp-element-button,
body.jetpack-form-bare-preview button[type="submit"]
) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the problem just outset, and why the rest of the styles then here too?

I don't fully understand the problem this CSS solves and ideally we'd have as little CSS like this around so looking for a way to reduce :-)

$rendered_form = (string) ob_get_clean();

// Form frontend stylesheet.
wp_enqueue_style( 'grunion.css' );
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it help to enqueue button block styles here if they aren't loaded otherwise?

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants