diff --git a/packages/pluggableWidgets/rich-text-web/CHANGELOG.md b/packages/pluggableWidgets/rich-text-web/CHANGELOG.md index 988944d6cd..557cc1ec52 100644 --- a/packages/pluggableWidgets/rich-text-web/CHANGELOG.md +++ b/packages/pluggableWidgets/rich-text-web/CHANGELOG.md @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] +### Fixed + +- We fixed an issue where the "Enable spell checking" setting had no effect. + ## [5.1.0] - 2026-09-29 ### Added diff --git a/packages/pluggableWidgets/rich-text-web/src/__tests__/RichText.spellCheck.spec.tsx b/packages/pluggableWidgets/rich-text-web/src/__tests__/RichText.spellCheck.spec.tsx new file mode 100644 index 0000000000..c02c2417a7 --- /dev/null +++ b/packages/pluggableWidgets/rich-text-web/src/__tests__/RichText.spellCheck.spec.tsx @@ -0,0 +1,78 @@ +import "@testing-library/jest-dom"; +import { render } from "@testing-library/react"; +import { EditableValueBuilder } from "@mendix/widget-plugin-test-utils"; +import { RichTextContainerProps, StatusBarContentEnum } from "../../typings/RichTextProps"; +import RichText from "../RichText"; + +describe("Rich Text spell checking", () => { + let defaultProps: RichTextContainerProps; + beforeEach(() => { + defaultProps = { + name: "RichText", + id: "RichText1", + stringAttribute: new EditableValueBuilder().withValue("

Rich text

").build(), + preset: "basic", + toolbarLocation: "bottom", + widthUnit: "percentage", + width: 100, + heightUnit: "percentageOfWidth", + height: 75, + toolbarConfig: "basic", + history: true, + fontStyle: true, + fontScript: true, + fontColor: true, + code: true, + indent: true, + embed: true, + align: true, + list: true, + remove: true, + header: true, + view: true, + tableBetter: false, + helpButton: true, + advancedConfig: [], + readOnlyStyle: "text", + tabIndex: 0, + onChangeType: "onLeave", + enableStatusBar: false, + dialogStyle: "inline", + statusBarContent: "wordCount" as StatusBarContentEnum, + spellCheck: false, + minHeightUnit: "none", + maxHeightUnit: "none", + maxHeight: 0, + minHeight: 75, + OverflowY: "auto", + customFonts: [], + enableDefaultUpload: true, + linkValidation: true, + styleDataFormat: "inline" + }; + }); + + const getEditable = (container: HTMLElement): HTMLElement => { + const editable = container.querySelector(".ProseMirror"); + expect(editable).not.toBeNull(); + return editable!; + }; + + it("enables spell checking on the editable area when spellCheck is true", () => { + const { container } = render(); + expect(getEditable(container)).toHaveAttribute("spellcheck", "true"); + }); + + it("disables spell checking on the editable area when spellCheck is false", () => { + const { container } = render(); + expect(getEditable(container)).toHaveAttribute("spellcheck", "false"); + }); + + it("follows spellCheck changes after the editor is created", () => { + const { container, rerender } = render(); + expect(getEditable(container)).toHaveAttribute("spellcheck", "false"); + + rerender(); + expect(getEditable(container)).toHaveAttribute("spellcheck", "true"); + }); +}); diff --git a/packages/pluggableWidgets/rich-text-web/src/__tests__/__snapshots__/RichText.spec.tsx.snap b/packages/pluggableWidgets/rich-text-web/src/__tests__/__snapshots__/RichText.spec.tsx.snap index 185376be7d..ed02629b9e 100644 --- a/packages/pluggableWidgets/rich-text-web/src/__tests__/__snapshots__/RichText.spec.tsx.snap +++ b/packages/pluggableWidgets/rich-text-web/src/__tests__/__snapshots__/RichText.spec.tsx.snap @@ -206,6 +206,7 @@ exports[`Rich Text renders richtext widget 1`] = ` class="tiptap ProseMirror" contenteditable="true" role="textbox" + spellcheck="true" tabindex="0" translate="no" > @@ -690,6 +691,7 @@ exports[`Rich Text renders richtext widget with different config 1`] = ` class="tiptap ProseMirror" contenteditable="true" role="textbox" + spellcheck="true" tabindex="0" translate="no" > @@ -742,6 +744,7 @@ exports[`Rich Text renders richtext widget with readonly config 1`] = ` class="tiptap ProseMirror" contenteditable="false" role="textbox" + spellcheck="true" translate="no" >

@@ -1223,6 +1227,7 @@ exports[`Rich Text renders with both word and character count 1`] = ` class="tiptap ProseMirror" contenteditable="true" role="textbox" + spellcheck="true" tabindex="0" translate="no" > @@ -1462,6 +1467,7 @@ exports[`Rich Text renders with character count status bar 1`] = ` class="tiptap ProseMirror" contenteditable="true" role="textbox" + spellcheck="true" tabindex="0" translate="no" > diff --git a/packages/pluggableWidgets/rich-text-web/src/components/Editor.tsx b/packages/pluggableWidgets/rich-text-web/src/components/Editor.tsx index 7058ef7daf..f3af983290 100644 --- a/packages/pluggableWidgets/rich-text-web/src/components/Editor.tsx +++ b/packages/pluggableWidgets/rich-text-web/src/components/Editor.tsx @@ -64,6 +64,7 @@ export interface EditorProps extends Pick< | "advancedConfig" | "customFonts" | "helpButton" + | "spellCheck" | "onFocus" | "onBlur" | "onLoad" @@ -226,6 +227,7 @@ const Editor = forwardRef((props, ref) => { imageSourceContent, enableDefaultUpload, dialogStyle = "inline", + spellCheck, ...others } = props; const actionRef = useMemo( @@ -366,6 +368,11 @@ const Editor = forwardRef((props, ref) => { }, content: defaultValue || "", editable: !readOnly, + editorProps: { + // Tiptap only adds `role="textbox"` when the view is created; re-renders + // apply these attributes as-is, so keep the role here to not lose it. + attributes: { role: "textbox", spellcheck: String(spellCheck) } + }, onUpdate: ({ editor }) => { const html = editor.isEmpty ? "" : editor.getHTML(); onUpdate?.(html); diff --git a/packages/pluggableWidgets/rich-text-web/src/components/EditorWrapper.tsx b/packages/pluggableWidgets/rich-text-web/src/components/EditorWrapper.tsx index 9742024f03..c7fa6caec2 100644 --- a/packages/pluggableWidgets/rich-text-web/src/components/EditorWrapper.tsx +++ b/packages/pluggableWidgets/rich-text-web/src/components/EditorWrapper.tsx @@ -42,6 +42,7 @@ function EditorWrapper(props: EditorWrapperProps): ReactElement { customFonts, toolbarLocation, readOnlyStyle, + spellCheck, onFocus, onBlur, onLoad, @@ -143,6 +144,7 @@ function EditorWrapper(props: EditorWrapperProps): ReactElement { helpButton={helpButton} advancedConfig={advancedConfig} customFonts={customFonts} + spellCheck={spellCheck} toolbarLocation={ stringAttribute.readOnly && readOnlyStyle !== "text" ? "hide" : toolbarLocation }