Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WC-2804]Update Rich Text #1423

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/pluggableWidgets/rich-text-web/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

## [Unreleased]

### Fixed

- We fixed minor HTML bugs whereas rich text will add extra new lines on saving value.
- We fixed rich text accessibility with tab keypress. Pressing tab will now allow you to directly focus on editor and Alt + F10 will brings you directly to toolbar.

## [4.2.0] - 2025-01-15

### Fixed
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion packages/pluggableWidgets/rich-text-web/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@mendix/rich-text-web",
"widgetName": "RichText",
"version": "4.2.0",
"version": "4.3.0",
"description": "Rich inline or toolbar text editing",
"copyright": "© Mendix Technology BV 2025. All rights reserved.",
"repository": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,9 @@ describe("Rich Text", () => {
const component = render(<RichText {...defaultProps} />);
expect(component.container).toMatchSnapshot();
});

it("renders richtext widget with different config", () => {
const component = render(<RichText {...defaultProps} toolbarLocation={"top"} preset={"full"} />);
expect(component.container).toMatchSnapshot();
});
});

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ export function FormatsContainer({ presetValue, children }: ToolbarConsumerConte
const toolbarContextValue = useContext(ToolbarContext);
return (
<If condition={presetValue === undefined || toolbarContextValue.presetValue >= presetValue}>
<span className="ql-formats">{children}</span>
<span className="ql-formats" tabIndex={-1}>
{children}
</span>
</If>
);
}
Expand All @@ -42,7 +44,14 @@ export function ToolbarButton({
const toolbarContextValue = useContext(ToolbarContext);
return (
<If condition={presetValue === undefined || toolbarContextValue.presetValue >= presetValue}>
<button className={className} onClick={onClick} value={value} title={title} aria-label={title}>
<button
className={className}
onClick={onClick}
value={value}
title={title}
aria-label={title}
tabIndex={-1}
>
{children}
</button>
</If>
Expand All @@ -53,7 +62,7 @@ export function ToolbarDropdown({ presetValue, className, value, title }: Toolba
const toolbarContextValue = useContext(ToolbarContext);
return (
<If condition={presetValue === undefined || toolbarContextValue.presetValue >= presetValue}>
<select className={className} title={title} aria-label={title}>
<select className={className} title={title} aria-label={title} tabIndex={-1}>
{Array.isArray(value) ? (
value.map(v => (
<option value={v.value || v} key={v.value || v}>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,23 @@ export function enterKeyKeyboardHandler(this: Keyboard, range: Range, context: C
this.quill.format(name, context.format[name], Quill.sources.USER);
});
}

// focus to first toolbar button
export function gotoToolbarKeyboardHandler(this: Keyboard, _range: Range, _context: Context): void {
const toolbar = this.quill.container.parentElement?.parentElement?.querySelector(".widget-rich-text-toolbar");
(toolbar?.querySelector(".ql-formats button") as HTMLElement)?.focus();
}

// focus to status bar button (exit editor)
export function gotoStatusBarKeyboardHandler(this: Keyboard, _range: Range, context: Context): boolean | void {
if (context.format.table) {
return true;
}

const statusBar = this.quill.container.parentElement?.parentElement?.nextElementSibling;
if (statusBar) {
(statusBar as HTMLElement)?.focus();
} else {
this.quill.blur();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@ import {
} from "react";
import "../utils/customPluginRegisters";
import MxQuill from "../utils/MxQuill";
import { enterKeyKeyboardHandler, getIndentHandler } from "./CustomToolbars/toolbarHandlers";
import {
enterKeyKeyboardHandler,
getIndentHandler,
gotoStatusBarKeyboardHandler,
gotoToolbarKeyboardHandler
} from "./CustomToolbars/toolbarHandlers";
import { useEmbedModal } from "./CustomToolbars/useEmbedModal";
import Dialog from "./ModalDialog/Dialog";

Expand Down Expand Up @@ -84,6 +89,15 @@ const Editor = forwardRef((props: EditorProps, ref: MutableRefObject<Quill | nul
enter: {
key: "Enter",
handler: enterKeyKeyboardHandler
},
focusTab: {
key: "F10",
altKey: true,
handler: gotoToolbarKeyboardHandler
},
tab: {
key: "Tab",
handler: gotoStatusBarKeyboardHandler
}
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export default function EditorWrapper(props: EditorWrapperProps): ReactElement {
}
}
}, 200),
[stringAttribute]
[stringAttribute, onChange, onChangeType]
);
const calculateWordCount = useCallback(
(quill: Quill | null): void => {
Expand Down Expand Up @@ -152,9 +152,18 @@ export default function EditorWrapper(props: EditorWrapperProps): ReactElement {
<div
className={classNames(
"flexcontainer",
toolbarLocation === "bottom" ? "flex-column" : "flex-column-reverse"
toolbarLocation === "bottom" ? "flex-column-reverse" : "flex-column"
)}
>
<If condition={!shouldHideToolbar && toolbarOptions === undefined}>
<Toolbar
ref={toolbarRef}
id={toolbarId}
preset={preset}
quill={quillRef.current}
toolbarContent={toolbarPreset}
/>
</If>
<Editor
theme={"snow"}
ref={quillRef}
Expand All @@ -172,18 +181,9 @@ export default function EditorWrapper(props: EditorWrapperProps): ReactElement {
readOnly={stringAttribute.readOnly}
key={`${toolbarId}_${stringAttribute.readOnly}`}
/>
<If condition={!shouldHideToolbar && toolbarOptions === undefined}>
<Toolbar
ref={toolbarRef}
id={toolbarId}
preset={preset}
quill={quillRef.current}
toolbarContent={toolbarPreset}
/>
</If>
</div>
{enableStatusBar && (
<div className="widget-rich-text-footer">
<div className="widget-rich-text-footer" tabIndex={-1}>
{wordCount} word{wordCount > 1 ? "s" : ""}
</div>
)}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,41 @@ export interface ToolbarProps {
toolbarContent: toolbarContentType[];
}

const ToolbarKeyDownHandler = (e: React.KeyboardEvent<HTMLDivElement>): void => {
const activeElement = document.activeElement as HTMLElement;
const parentElement = activeElement?.parentElement;
if (!parentElement?.classList.contains("ql-formats")) {
return;
}
e.preventDefault();
if (e.key === "Tab") {
const nextFocusElementParent = e.shiftKey
? (parentElement.previousElementSibling as HTMLElement)
: (parentElement.nextElementSibling as HTMLElement);
if (nextFocusElementParent) {
const nextElement = nextFocusElementParent.firstChild as HTMLElement;
if (nextElement) {
nextElement.focus();
e.stopPropagation();
}
}
} else if (e.key === "ArrowRight") {
const nextElementSibling = activeElement.nextElementSibling as HTMLElement;
if (nextElementSibling) {
nextElementSibling.focus();
e.stopPropagation();
}
} else if (e.key === "ArrowLeft") {
const previousElementSibling = activeElement.previousElementSibling as HTMLElement;
if (previousElementSibling) {
previousElementSibling.focus();
e.stopPropagation();
}
} else if (e.key === "Enter") {
activeElement.click();
}
};

const Toolbar = forwardRef((props: ToolbarProps, ref: RefObject<HTMLDivElement>): ReactElement => {
const { id, preset, style, quill, toolbarContent } = props;
const presetValue = presetToNumberConverter(preset);
Expand All @@ -23,7 +58,7 @@ const Toolbar = forwardRef((props: ToolbarProps, ref: RefObject<HTMLDivElement>)
presetValue
}}
>
<div id={id} style={style} ref={ref} className="widget-rich-text-toolbar">
<div id={id} style={style} ref={ref} className="widget-rich-text-toolbar" onKeyDown={ToolbarKeyDownHandler}>
{toolbarContent.map((toolbarGroup, index) => {
return (
<FormatsContainer presetValue={toolbarGroup.presetValue} key={`toolbargroup_${id}_${index}`}>
Expand Down
2 changes: 1 addition & 1 deletion packages/pluggableWidgets/rich-text-web/src/package.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<package xmlns="http://www.mendix.com/package/1.0/">
<clientModule name="RichText" version="4.2.0" xmlns="http://www.mendix.com/clientModule/1.0/">
<clientModule name="RichText" version="4.3.0" xmlns="http://www.mendix.com/clientModule/1.0/">
<widgetFiles>
<widgetFile path="RichText.xml" />
</widgetFiles>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

$rte-border-color-default: #ced0d3;
$rte-gray-ligher: #f8f8f8;
$rte-brand-primary: #264ae5;

.widget-rich-text {
position: relative;
Expand Down Expand Up @@ -43,6 +44,12 @@ $rte-gray-ligher: #f8f8f8;
max-height: 250px;
overflow-y: auto;
}

.ql-formats {
button:focus {
font-weight: bold;
}
}
}

.widget-rich-text-footer {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class Button extends Inline {
return domNode;
}

static formats(domNode: Element): Record<string, string | null> {
static formats(domNode: Element): any {
return ATTRIBUTES.reduce((formats: Record<string, string | null>, attribute) => {
if (domNode.hasAttribute(attribute)) {
formats[attribute] = domNode.getAttribute(attribute);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ export default class MendixTheme extends SnowTheme {
fontPicker?: Picker = undefined;
buildPickers(selects: NodeListOf<HTMLSelectElement>, icons: Record<string, string | Record<string, string>>): void {
super.buildPickers(selects, icons);

this.pickers.forEach(picker => {
const pickerLabel = picker.container.querySelector(".ql-picker-label");
if (pickerLabel) {
pickerLabel.setAttribute("tabindex", "-1");
}
});
}

/**
Expand Down