Issue #3547306: Add interactive refinement capability to Field Widget Actions

Adds opt-in interactive refinement to Field Widget Actions: when enabled, an action button opens a modal that shows the generated content, lets the user iteratively refine it with follow-up prompts, and then inserts the result into the field. Refinement is off by default — existing actions are unaffected.

Approach

Built on the server-side Form API modal (FieldWidgetFormActionBase), per maintainer feedback — no custom modal JavaScript or CSS. The generated content and the refinement prompt are ordinary form elements; clicking Refine rebuilds the modal server-side (the same way validation errors refresh a modal), and Insert writes the result to the field. This replaces an earlier custom JS/CSS/Twig prototype, which has been removed.

Key changes

  • New FieldWidgetRefinableFormActionBase — base class for refinable actions. Owns the modal, the Insert / Refine / Cancel controls, the refine round-trip, and field insertion.
  • New RefinementAwareInterface (Drupal\field_widget_actions\RefinementAwareInterface) — plugins implement generateContent() (initial content when the modal opens) and refineContent() (revise from a prompt); isRefinementEnabled() is provided by the base.
  • Config options: enable_refinement and refinement_modal_title, shown only for refinement-capable plugins.
  • Format-aware editing: for formatted-text targets (CKEditor / text_format), the modal edits content as rich text so HTML (e.g. lists) survives Generate → Refine → Insert; plain-text targets (including the summary of a text_with_summary field) use a plain textarea.
  • Direct-fill preserved: when refinement is disabled and a plugin provides its own AJAX callback, the original direct field-fill behavior is kept — no modal.
  • Entity building on modal open: opening the modal builds the entity from the current form values and works on forms containing single-cardinality options_select / chosen_select fields, without surfacing unrelated required-field errors.
  • Documentation updated (docs/create.md).

How to test

  1. Add a field widget action to a text field and check Enable interactive refinement in its configuration.
  2. On a content add/edit form, click the action button — a modal opens with the generated content and a refinement prompt.
  3. Enter a prompt and click Refine — the modal refreshes with the revised content (the iteration counter increments).
  4. Click Insert — the content populates the field; Cancel closes without changes.
  5. On a CKEditor (text_format) field, generate an HTML list — it shows as a rendered list in the modal and inserts as a list (not a flattened blob).
  6. On a form that also has a required single-cardinality options_select field, confirm the modal opens with no error and no spurious "required" warning.

Test coverage

FunctionalJavascript tests cover: the refine flow (generate / refine / insert / cancel / empty-prompt), the direct-fill fallback when refinement is off, HTML preservation on a CKEditor field, the plain-text summary path, and modal-open on a form with a single-value options_select field.

Companion

Wiring specific AI automators to RefinementAwareInterface is handled in the companion AI module MR (issue #3586468).

Issue: #3547306

Edited by Edward Zwart

Merge request reports

Loading