Skip to content

feat(text-editor): add onFormSubmission callback#7831

Merged
tomdavies73 merged 2 commits intomasterfrom
FE-7597
Mar 26, 2026
Merged

feat(text-editor): add onFormSubmission callback#7831
tomdavies73 merged 2 commits intomasterfrom
FE-7597

Conversation

@tomdavies73
Copy link
Copy Markdown
Contributor

@tomdavies73 tomdavies73 commented Mar 11, 2026

fix #7737

Proposed behaviour

Adds a new onFormSubmission callback that is triggered when the parent form is submitted. This callback provides access to the editor's content in multiple formats, including htmlStringWithInlineStyles - HTML content with Lexical class names converted to inline styles.

This is a separate callback from onSave and is designed specifically for form submission workflows. The HTML with inline styles is useful when editor content needs to be used in contexts where stylesheets are not available, such as PDF generation or email templates.

Current behaviour

Currently, there is no onFormSubmission callback, also there is no mechanism for consumers to access inline HTML from the editor with inline css for external consumption.

Checklist

  • Commits follow our style guide
  • Related issues linked in commit messages if required
  • Screenshots are included in the PR if useful
  • All themes are supported if required
  • Unit tests added or updated if required
  • Playwright automation tests added or updated if required
  • Storybook added or updated if required
  • Translations added or updated (including creating or amending translation keys table in storybook) if required
  • Typescript d.ts file added or updated if required
  • Related docs have been updated if required

QA

  • Tested in provided StackBlitz sandbox/Storybook
  • Add new Playwright test coverage if required
  • Carbon implementation matches Design System/designs
  • UI Tests GitHub check reviewed if required

Additional context

Testing instructions

Trigger the onFormSubmission behaviour on the onFormSubmission story within TextEditor, assert the inline styles is correct

@tomdavies73 tomdavies73 self-assigned this Mar 11, 2026
@tomdavies73 tomdavies73 added the Work in progress This is a WIP PR so may not be ready for review label Mar 11, 2026
@tomdavies73 tomdavies73 requested a review from Copilot March 11, 2026 17:35
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the TextEditor component API/behaviour by removing the legacy cancel/save toolbar buttons, repurposing onSave to trigger on parent form submission, and adding a second onSave argument containing HTML with inline styles for portability.

Changes:

  • Removed onCancel support (props, UI, locale keys, docs, and tests) and removed the legacy save button UI.
  • Added a SavePlugin that listens for parent <form> submit events and calls onSave(formattedValues, htmlWithInlineStyles).
  • Added generateHTMLWithInlineStyles post-processing + updated Storybook/docs/tests to reflect the new onSave signature and behaviour.

Reviewed changes

Copilot reviewed 28 out of 28 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/locales/pt-pt.ts Removes legacy TextEditor save/cancel locale keys.
src/locales/locale.ts Removes legacy TextEditor save/cancel locale keys from the locale interface.
src/locales/fr-fr.ts Removes legacy TextEditor save/cancel locale keys.
src/locales/fr-ca.ts Removes legacy TextEditor save/cancel locale keys.
src/locales/es-es.ts Removes legacy TextEditor save/cancel locale keys.
src/locales/en-gb.ts Removes legacy TextEditor save/cancel locale keys.
src/locales/de-de.ts Removes legacy TextEditor save/cancel locale keys.
src/components/text-editor/text-editor.test.tsx Updates unit tests for new onSave form-submit semantics and removes old cancel/save button tests.
src/components/text-editor/text-editor.stories.tsx Updates Storybook OnSave to submit via a form and display inline-styled HTML output.
src/components/text-editor/text-editor.pw.tsx Removes Playwright tests tied to legacy save/cancel toolbar buttons.
src/components/text-editor/text-editor.mdx Updates docs for new onSave behaviour/signature and removes translation keys for legacy buttons.
src/components/text-editor/text-editor.component.tsx Removes legacy deprecations + toolbar wiring and mounts new SavePlugin.
src/components/text-editor/text-editor-test.stories.tsx Removes onCancel usage in test stories.
src/components/text-editor/components.test-pw.tsx Removes Playwright fixture components that relied on legacy save/cancel buttons.
src/components/text-editor/internal/utils/interfaces.types.ts Removes onCancel, changes onSave signature, removes SaveButtonProps.
src/components/text-editor/internal/utils/helpers.ts Adds generateHTMLWithInlineStyles helper and exports it.
src/components/text-editor/internal/utils/helpers.test.ts Adds tests for generateHTMLWithInlineStyles.
src/components/text-editor/internal/ui/Toolbar/toolbar.style.ts Removes CommandButtons styling used by legacy buttons.
src/components/text-editor/internal/ui/Toolbar/toolbar.component.tsx Removes legacy save/cancel button rendering.
src/components/text-editor/internal/ui/Toolbar/buttons/save.component.tsx Deletes legacy Save button component.
src/components/text-editor/internal/ui/Toolbar/buttons/index.ts Removes Save button export.
src/components/text-editor/internal/ui/Toolbar/buttons/buttons.test.tsx Deletes tests specific to legacy Save button behaviour.
src/components/text-editor/internal/ui/ContentEditor/content-editor.test.tsx Adds coverage for a blur-related branch.
src/components/text-editor/internal/plugins/index.ts Exports new SavePlugin.
src/components/text-editor/internal/plugins/SavePlugin/save.plugin.tsx Implements new form-submit listener logic that calls onSave with two args.
src/components/text-editor/internal/plugins/SavePlugin/save.plugin.test.tsx Adds unit tests for SavePlugin event wiring and callback behaviour.
src/components/text-editor/internal/plugins/SavePlugin/index.ts Barrel exports for SavePlugin.
skills/carbon-react/components/text-editor.md Updates generated/skills documentation for new onSave behaviour and signature.
Comments suppressed due to low confidence (1)

src/components/text-editor/text-editor.pw.tsx:510

  • Playwright coverage for the new onSave behaviour appears to have been removed without replacement. Since onSave now fires on parent form submission (and must ignore internal dialog forms), it would be good to add/update a Playwright test that wraps TextEditor in a form with a submit button and asserts the callback is triggered (and not triggered by the hyperlink dialog save).
test.describe("Functionality tests", () => {
  test.describe("onBlur", () => {
    test("fires when the editor loses focus", async ({ mount, page }) => {
      let currentValue = false;


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

import Logger from "../../../../__internal__/utils/logger";

const fontFamily = "font-family: 'Sage UI', sans-serif;";
const linkStyles = `color: #007e45ff; cursor: pointer; text-decoration: underline; ${fontFamily}`;
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

The new inline link color uses 8-digit hex (#007e45ff). Because this HTML output is explicitly intended to be portable for email/external consumers, prefer a more broadly supported representation (e.g. 6-digit hex #007e45 or rgb/rgba), ideally sourced from an existing theme/token rather than a hard-coded literal.

Suggested change
const linkStyles = `color: #007e45ff; cursor: pointer; text-decoration: underline; ${fontFamily}`;
const linkStyles = `color: #007e45; cursor: pointer; text-decoration: underline; ${fontFamily}`;

Copilot uses AI. Check for mistakes.

If the `onSave` property is not provided, the `Save` button will not be displayed.
1. **`formattedValues`**: An object containing the serialized editor content:
- `htmlString`: A HTML representation of the editor content, as a string.
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

In this onSave docs section, "A HTML representation" is grammatically incorrect; it should be "An HTML representation" (also helps keep wording consistent for public docs).

Suggested change
- `htmlString`: A HTML representation of the editor content, as a string.
- `htmlString`: An HTML representation of the editor content, as a string.

Copilot uses AI. Check for mistakes.
To handle the content of the editor when a form containing the editor is submitted, you can set the `onSave` property to a function. The callback function returns two parameters:

1. **`formattedValues`**: An object containing the serialized editor content:
- `htmlString`: A HTML representation of the editor content, as a string.
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

The onSave docs here say "A HTML representation"; this should be "An HTML representation".

Suggested change
- `htmlString`: A HTML representation of the editor content, as a string.
- `htmlString`: An HTML representation of the editor content, as a string.

Copilot uses AI. Check for mistakes.
Comment on lines +20 to +22
* <TextEditor labelText="..." onSave={(values, html) => console.log(values, html)}>
* <SavePlugin onSave={handleSave} />
* </TextEditor>
Copy link

Copilot AI Mar 11, 2026

Choose a reason for hiding this comment

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

The JSDoc @example here suggests consumers render as a child of , but SavePlugin is an internal plugin that TextEditor mounts itself. This example is misleading; either remove it or replace it with an example that shows TextEditor inside a parent

and using TextEditor’s onSave prop.

Suggested change
* <TextEditor labelText="..." onSave={(values, html) => console.log(values, html)}>
* <SavePlugin onSave={handleSave} />
* </TextEditor>
* <form onSubmit={handleSubmit}>
* <TextEditor
* labelText="..."
* onSave={(values, html) => {
* console.log(values, html);
* }}
* />
* </form>

Copilot uses AI. Check for mistakes.
@tomdavies73 tomdavies73 changed the title feat(text-editor): repurpose onSave callback and remove onCancel ballback feat(text-editor): add onFormSubmission callback Mar 13, 2026
@tomdavies73 tomdavies73 added Pending Review Pending QA No UX QA Required and removed Work in progress This is a WIP PR so may not be ready for review labels Mar 13, 2026
@tomdavies73 tomdavies73 force-pushed the FE-7597 branch 2 times, most recently from a762b63 to f8235e6 Compare March 13, 2026 11:49

The callback receives an object containing:

1. **`formattedValues`**: An object containing the serialized editor content:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

suggestion: use British English

Suggested change
1. **`formattedValues`**: An object containing the serialized editor content:
1. **`formattedValues`**: An object containing the serialised editor content:

return form;
};

describe("FormSubmissionPlugin", () => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

comment(non-blocking): describe and it blocks should be written in continuous prose

});
});

describe("generateHTMLWithInlineStyles", () => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

comment(non-blocking): describe and it blocks should be written in continuous prose

};

/**
* Post-processes HTML serialized from the Lexical editor, converting class-based
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

suggestion: use British English

Suggested change
* Post-processes HTML serialized from the Lexical editor, converting class-based
* Post-processes HTML serialised from the Lexical editor, converting class-based


The callback receives an object containing:

1. **`formattedValues`**: An object containing the serialized editor content:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

suggestion: use British English

Suggested change
1. **`formattedValues`**: An object containing the serialized editor content:
1. **`formattedValues`**: An object containing the serialised editor content:

nineteen88
nineteen88 previously approved these changes Mar 24, 2026
@dariusbercea-sage dariusbercea-sage marked this pull request as ready for review March 25, 2026 13:43
@dariusbercea-sage dariusbercea-sage requested review from a team as code owners March 25, 2026 13:43
@dariusbercea-sage dariusbercea-sage requested a review from a team as a code owner March 25, 2026 13:43
Adds a new onFormSubmission callback that is triggered when the parent
form is submitted. This callback provides access to the editor's content in
multiple formats, including htmlStringWithInlineStyles - HTML content with
Lexical class names converted to inline styles.

This is a separate callback from onSave and is designed specifically for form
submission workflows. The HTML with inline styles is useful when editor content
needs to be used in contexts where stylesheets are not available, such as PDF
generation or email templates.

fix #7737
@tomdavies73 tomdavies73 merged commit 8f7f4e6 into master Mar 26, 2026
28 checks passed
@tomdavies73 tomdavies73 deleted the FE-7597 branch March 26, 2026 11:13
@carbonci
Copy link
Copy Markdown
Collaborator

🎉 This PR is included in version 158.39.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

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

Development

Successfully merging this pull request may close these issues.

Export HTML with styles in-line from TextEditor

6 participants