Tiptap RTE: Block selection (#19811)

* Removed `cursor: not-allowed` style

* Sets the `umb-rte-block` `user-select` to `all`

* Adds an "invisible" selection background to `umb-ref-rte-block`

* Sets the `umb-ufm-render` text-content to be visible

* Adds `aria-hidden` attribute

* Bumped version of test helper

* Fixed the failing tests due to UI changes

* Adds `pointer-events: none` to selection-background

---------

Co-authored-by: Nhu Dinh <hnd@umbraco.dk>
This commit is contained in:
Lee Kelleher
2025-07-31 10:39:30 +01:00
committed by GitHub
parent 4a37f06677
commit 965408df57
7 changed files with 40 additions and 13 deletions

View File

@@ -354,13 +354,14 @@ export class UmbBlockRteEntryElement extends UmbLitElement implements UmbPropert
:host {
position: relative;
display: block;
user-select: none;
user-select: all;
user-drag: auto;
white-space: nowrap;
}
:host(.ProseMirror-selectednode) {
umb-ref-rte-block {
cursor: not-allowed;
--uui-color-default-contrast: initial;
outline: 3px solid var(--uui-color-focus);
}
}

View File

@@ -49,6 +49,7 @@ export class UmbRefRteBlockElement extends UmbLitElement {
const blockValue = { ...this.content, $settings: this.settings };
return html`
<uui-ref-node standalone href=${(this.config?.showContentEdit ? this._workspaceEditPath : undefined) ?? ''}>
<div class="selection-background" aria-hidden="true">&emsp;</div>
<umb-icon slot="icon" .name=${this.icon}></umb-icon>
<umb-ufm-render slot="name" inline .markdown=${this.label} .value=${blockValue}></umb-ufm-render>
</uui-ref-node>
@@ -60,13 +61,34 @@ export class UmbRefRteBlockElement extends UmbLitElement {
:host {
display: block;
}
uui-ref-node {
min-height: var(--uui-size-16);
}
:host([unpublished]) umb-icon,
:host([unpublished]) umb-ufm-render {
opacity: 0.6;
}
/* HACK: Stretches a space character (&emsp;) to be full-width to make the RTE block appear text-selectable. [LK,NL] */
.selection-background {
position: absolute;
pointer-events: none;
font-size: 100vw;
inset: 0;
overflow: hidden;
z-index: 0;
}
umb-icon,
umb-ufm-render {
z-index: 1;
&::selection {
color: var(--uui-color-default-contrast);
}
}
`,
];
}

View File

@@ -50,6 +50,10 @@ export class UmbUfmRenderElement extends UmbLitElement {
static override styles = [
UmbTextStyles,
css`
:host {
position: relative;
}
* {
max-width: 100%;
word-wrap: break-word;

View File

@@ -8,7 +8,7 @@
"hasInstallScript": true,
"dependencies": {
"@umbraco/json-models-builders": "^2.0.37",
"@umbraco/playwright-testhelpers": "^16.0.29",
"@umbraco/playwright-testhelpers": "^16.0.32",
"camelize": "^1.0.0",
"dotenv": "^16.3.1",
"node-fetch": "^2.6.7"
@@ -66,9 +66,9 @@
}
},
"node_modules/@umbraco/playwright-testhelpers": {
"version": "16.0.29",
"resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-16.0.29.tgz",
"integrity": "sha512-Zk0Ip2rZO0T15mbjQqu9SXI9TFckja/Y4KpHCRzwRgTbkDKr9pT7TENCcvegymVX2GpH6Cs9fu7OPvUABLK9cg==",
"version": "16.0.32",
"resolved": "https://registry.npmjs.org/@umbraco/playwright-testhelpers/-/playwright-testhelpers-16.0.32.tgz",
"integrity": "sha512-HB/xHnu36XOyQjNnpSe1j9DoZ61tY7OvnkNQT73MhGcrhfnNdn/Hf+6nFN7gutUTcxn+L6COeXzexQclSjYr+g==",
"dependencies": {
"@umbraco/json-models-builders": "2.0.37",
"node-fetch": "^2.6.7"

View File

@@ -21,7 +21,7 @@
},
"dependencies": {
"@umbraco/json-models-builders": "^2.0.37",
"@umbraco/playwright-testhelpers": "^16.0.29",
"@umbraco/playwright-testhelpers": "^16.0.32",
"camelize": "^1.0.0",
"dotenv": "^16.3.1",
"node-fetch": "^2.6.7"

View File

@@ -108,7 +108,7 @@ test('can update property value nested in a block grid area with an RTE with a b
await umbracoUi.content.isFailedStateButtonVisible();
await umbracoUi.content.doesErrorNotificationHaveText(NotificationConstantHelper.error.documentCouldNotBePublished, true, true);
// Updates the textstring block with the correct value
await umbracoUi.content.clickBlockElementWithName(blockListElementTypeName);
await umbracoUi.content.clickBlockElementInRTEWithName(blockListElementTypeName);
await umbracoUi.content.clickEditBlockListEntryWithName(textStringElementTypeName);
await umbracoUi.content.enterPropertyValue(textStringElementDataTypeName, correctPropertyValue);
await umbracoUi.content.clickUpdateButtonForModalWithElementTypeNameAndGroupName(textStringElementTypeName, textStringElementGroupName);
@@ -124,7 +124,7 @@ test('can update property value nested in a block grid area with an RTE with a b
await umbracoUi.reloadPage();
// Waits to make sure the page has loaded
await umbracoUi.waitForTimeout(2000);
await umbracoUi.content.clickBlockElementWithName(blockListElementTypeName);
await umbracoUi.content.clickBlockElementInRTEWithName(blockListElementTypeName);
// Needs to wait to make sure it has loaded
await umbracoUi.waitForTimeout(2000);
await umbracoUi.content.clickEditBlockListEntryWithName(textStringElementTypeName);

View File

@@ -61,7 +61,7 @@ test('invariant document type with invariant tiptap RTE with invariant block wit
await umbracoUi.content.isSuccessStateVisibleForSaveAndPublishButton();
expect(await umbracoApi.document.isDocumentPublished(contentId)).toBeTruthy();
await umbracoUi.reloadPage();
await umbracoUi.content.clickBlockElementWithName(blockName);
await umbracoUi.content.clickBlockElementInRTEWithName(blockName);
await umbracoUi.content.doesPropertyContainValue(textStringName, textStringText);
});
@@ -128,7 +128,7 @@ test('variant document type with variant tiptap RTE with variant block with an v
await umbracoUi.content.doesSuccessNotificationHaveText(NotificationConstantHelper.success.published);
expect(await umbracoApi.document.isDocumentPublished(contentId)).toBeTruthy();
await umbracoUi.reloadPage();
await umbracoUi.content.clickBlockElementWithName(blockName);
await umbracoUi.content.clickBlockElementInRTEWithName(blockName);
await umbracoUi.content.doesPropertyContainValue(textStringName, textStringText);
});
@@ -154,7 +154,7 @@ test('variant document type with invariant tiptap RTE with variant block with an
await umbracoUi.content.doesSuccessNotificationHaveText(NotificationConstantHelper.success.published);
expect(await umbracoApi.document.isDocumentPublished(contentId)).toBeTruthy();
await umbracoUi.reloadPage();
await umbracoUi.content.clickBlockElementWithName(blockName);
await umbracoUi.content.clickBlockElementInRTEWithName(blockName);
await umbracoUi.content.doesPropertyContainValue(textStringName, textStringText);
});
@@ -180,6 +180,6 @@ test('variant document type with invariant tiptap RTE with variant block with an
await umbracoUi.content.doesSuccessNotificationHaveText(NotificationConstantHelper.success.published);
expect(await umbracoApi.document.isDocumentPublished(contentId)).toBeTruthy();
await umbracoUi.reloadPage();
await umbracoUi.content.clickBlockElementWithName(blockName);
await umbracoUi.content.clickBlockElementInRTEWithName(blockName);
await umbracoUi.content.doesPropertyContainValue(textStringName, textStringText);
});