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 implementgenerateContent()(initial content when the modal opens) andrefineContent()(revise from a prompt);isRefinementEnabled()is provided by the base. - Config options:
enable_refinementandrefinement_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 thesummaryof atext_with_summaryfield) 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_selectfields, without surfacing unrelated required-field errors. - Documentation updated (
docs/create.md).
How to test
- Add a field widget action to a text field and check Enable interactive refinement in its configuration.
- On a content add/edit form, click the action button — a modal opens with the generated content and a refinement prompt.
- Enter a prompt and click Refine — the modal refreshes with the revised content (the iteration counter increments).
- Click Insert — the content populates the field; Cancel closes without changes.
- 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). - On a form that also has a required single-cardinality
options_selectfield, 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