diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/cascading-menu-popover/cascading-menu-popover.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/cascading-menu-popover/cascading-menu-popover.element.ts
index 047b6c05891c..8709139f6425 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/cascading-menu-popover/cascading-menu-popover.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/cascading-menu-popover/cascading-menu-popover.element.ts
@@ -9,6 +9,7 @@ export type UmbCascadingMenuItem = {
element?: HTMLElement;
separatorAfter?: boolean;
style?: string;
+ isActive?: () => boolean | undefined;
execute?: () => void;
};
@@ -21,8 +22,12 @@ export class UmbCascadingMenuPopoverElement extends UmbElementMixin(UUIPopoverCo
return this.shadowRoot?.querySelector(`#${popoverId}`) as UUIPopoverContainerElement;
}
- #onMouseEnter(item: UmbCascadingMenuItem, popoverId: string) {
- if (!item.items?.length) return;
+ #isMenuActive(items?: UmbCascadingMenuItem[]): boolean {
+ return !!items?.some((item) => item.isActive?.() || this.#isMenuActive(item.items));
+ }
+
+ #onMouseEnter(item: UmbCascadingMenuItem, popoverId?: string) {
+ if (!item.items?.length || !popoverId) return;
const popover = this.#getPopoverById(popoverId);
if (!popover) return;
@@ -33,7 +38,9 @@ export class UmbCascadingMenuPopoverElement extends UmbElementMixin(UUIPopoverCo
popover.showPopover();
}
- #onMouseLeave(item: UmbCascadingMenuItem, popoverId: string) {
+ #onMouseLeave(item: UmbCascadingMenuItem, popoverId?: string) {
+ if (!popoverId) return;
+
const popover = this.#getPopoverById(popoverId);
if (!popover) return;
@@ -43,12 +50,16 @@ export class UmbCascadingMenuPopoverElement extends UmbElementMixin(UUIPopoverCo
popover.hidePopover();
}
- #onClick(item: UmbCascadingMenuItem, popoverId: string) {
+ #onClick(item: UmbCascadingMenuItem, popoverId?: string) {
item.execute?.();
- setTimeout(() => {
- this.#onMouseLeave(item, popoverId);
- }, 100);
+ if (!popoverId) {
+ setTimeout(() => {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ this.hidePopover();
+ }, 100);
+ }
}
override render() {
@@ -64,14 +75,15 @@ export class UmbCascadingMenuPopoverElement extends UmbElementMixin(UUIPopoverCo
}
#renderItem(item: UmbCascadingMenuItem, index: number) {
- const popoverId = `item-${index}`;
+ const popoverId = item.items ? `menu-${index}` : undefined;
const element = item.element;
- if (element) {
+ if (element && popoverId) {
element.setAttribute('popovertarget', popoverId);
}
const label = this.localize.string(item.label);
+ const isActive = item.isActive?.() || this.#isMenuActive(item.items) || false;
return html`
this.#onClick(item, popoverId)}>
${when(item.icon, (icon) => html``)}
`;
}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/toolbar/style-menu.tiptap-toolbar-api.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/toolbar/style-menu.tiptap-toolbar-api.ts
index dda2e85f260c..381607675acd 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/toolbar/style-menu.tiptap-toolbar-api.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/toolbar/style-menu.tiptap-toolbar-api.ts
@@ -2,14 +2,28 @@ import { UmbTiptapToolbarElementApiBase } from '../../extensions/base.js';
import type { MetaTiptapToolbarStyleMenuItem } from '../../extensions/types.js';
import type { ChainedCommands, Editor } from '@umbraco-cms/backoffice/external/tiptap';
+type UmbTiptapToolbarStyleMenuCommandType = {
+ type: string;
+ command: (chain: ChainedCommands) => ChainedCommands;
+ isActive?: (editor?: Editor) => boolean | undefined;
+};
+
export default class UmbTiptapToolbarStyleMenuApi extends UmbTiptapToolbarElementApiBase {
- #commands: Record ChainedCommands }> = {
- h1: { type: 'heading', command: (chain) => chain.toggleHeading({ level: 1 }) },
- h2: { type: 'heading', command: (chain) => chain.toggleHeading({ level: 2 }) },
- h3: { type: 'heading', command: (chain) => chain.toggleHeading({ level: 3 }) },
- h4: { type: 'heading', command: (chain) => chain.toggleHeading({ level: 4 }) },
- h5: { type: 'heading', command: (chain) => chain.toggleHeading({ level: 5 }) },
- h6: { type: 'heading', command: (chain) => chain.toggleHeading({ level: 6 }) },
+ #headingCommand(level: 1 | 2 | 3 | 4 | 5 | 6): UmbTiptapToolbarStyleMenuCommandType {
+ return {
+ type: 'heading',
+ command: (chain) => chain.toggleHeading({ level }),
+ isActive: (editor) => editor?.isActive('heading', { level }),
+ };
+ }
+
+ #commands: Record = {
+ h1: this.#headingCommand(1),
+ h2: this.#headingCommand(2),
+ h3: this.#headingCommand(3),
+ h4: this.#headingCommand(4),
+ h5: this.#headingCommand(5),
+ h6: this.#headingCommand(6),
p: { type: 'paragraph', command: (chain) => chain.setParagraph() },
blockquote: { type: 'blockquote', command: (chain) => chain.toggleBlockquote() },
code: { type: 'code', command: (chain) => chain.toggleCode() },
@@ -24,6 +38,20 @@ export default class UmbTiptapToolbarStyleMenuApi extends UmbTiptapToolbarElemen
ul: { type: 'bulletList', command: (chain) => chain.toggleBulletList() },
};
+ override isActive(editor?: Editor, item?: MetaTiptapToolbarStyleMenuItem) {
+ if (!editor || !item?.data) return false;
+
+ const { tag, id, class: className } = item.data;
+ const ext = tag ? this.#commands[tag] : null;
+ const attrs = editor?.getAttributes(ext?.type ?? 'paragraph');
+
+ const tagMatch = !tag ? true : ext ? (ext.isActive?.(editor) ?? editor?.isActive(ext.type) ?? false) : false;
+ const idMatch = !id ? true : attrs.id === id;
+ const classMatch = !className ? true : attrs.class?.includes(className) === true;
+
+ return tagMatch && idMatch && classMatch;
+ }
+
override execute(editor?: Editor, item?: MetaTiptapToolbarStyleMenuItem) {
if (!editor || !item?.data) return;
const { tag, id, class: className } = item.data;
diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/toolbar/tiptap-toolbar-menu.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/toolbar/tiptap-toolbar-menu.element.ts
index 7f7726eb1040..4ffa6538d43d 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/toolbar/tiptap-toolbar-menu.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/components/toolbar/tiptap-toolbar-menu.element.ts
@@ -99,13 +99,18 @@ export class UmbTiptapToolbarMenuElement extends UmbLitElement {
style: item.appearance?.style ?? item.style,
separatorAfter: item.separatorAfter,
element,
+ isActive: () => this.api?.isActive(this.editor, item),
execute: () => this.api?.execute(this.editor, item),
};
}
+ #isMenuActive(items?: UmbCascadingMenuItem[]): boolean {
+ return !!items?.some((item) => item.isActive?.() || this.#isMenuActive(item.items));
+ }
+
readonly #onEditorUpdate = () => {
if (this.api && this.editor && this.manifest) {
- this.isActive = this.api.isActive(this.editor);
+ this.isActive = this.api.isActive(this.editor) || this.#isMenuActive(this.#menu) || false;
}
};
@@ -117,8 +122,8 @@ export class UmbTiptapToolbarMenuElement extends UmbLitElement {
() => html`
${when(
@@ -130,7 +135,11 @@ export class UmbTiptapToolbarMenuElement extends UmbLitElement {
`,
() => html`
-
+
${label}
diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/table/components/table-toolbar-menu.element.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/table/components/table-toolbar-menu.element.ts
index d57dc1340158..c59e0322659b 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/table/components/table-toolbar-menu.element.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/table/components/table-toolbar-menu.element.ts
@@ -32,7 +32,7 @@ export class UmbTiptapTableToolbarMenuElement extends UmbTiptapToolbarMenuElemen
`,
)}
${this.renderMenu()}
-
+
`;
diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/table/table.tiptap-toolbar-api.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/table/table.tiptap-toolbar-api.ts
index 6fd0e5bba418..569b913fe667 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/table/table.tiptap-toolbar-api.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/table/table.tiptap-toolbar-api.ts
@@ -29,6 +29,11 @@ export class UmbTiptapToolbarTableExtensionApi extends UmbTiptapToolbarElementAp
tableProperties: (editor) => this.#tableProperties(editor),
};
+ override isActive(editor?: Editor, item?: unknown) {
+ if (!item) return super.isActive(editor);
+ return false;
+ }
+
async #tableProperties(editor?: Editor) {
if (!editor || !editor.isActive('table')) return;
diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/font-family.tiptap-toolbar-api.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/font-family.tiptap-toolbar-api.ts
index 41f698d3f973..4b4c92e03f81 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/font-family.tiptap-toolbar-api.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/font-family.tiptap-toolbar-api.ts
@@ -3,6 +3,11 @@ import type { MetaTiptapToolbarMenuItem } from '../types.js';
import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
export default class UmbTiptapToolbarFontFamilyExtensionApi extends UmbTiptapToolbarElementApiBase {
+ override isActive(editor?: Editor, item?: MetaTiptapToolbarMenuItem) {
+ const styles = editor?.getAttributes('span')?.style;
+ return styles?.includes(`font-family: ${item?.data};`) === true;
+ }
+
override execute(editor?: Editor, item?: MetaTiptapToolbarMenuItem) {
if (!item?.data) return;
editor?.chain().focus().toggleSpanStyle(`font-family: ${item.data};`).run();
diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/font-size.tiptap-toolbar-api.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/font-size.tiptap-toolbar-api.ts
index 3b7f4c5333f7..608807715968 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/font-size.tiptap-toolbar-api.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/toolbar/font-size.tiptap-toolbar-api.ts
@@ -3,6 +3,11 @@ import type { MetaTiptapToolbarMenuItem } from '../types.js';
import type { Editor } from '@umbraco-cms/backoffice/external/tiptap';
export default class UmbTiptapToolbarFontFamilyExtensionApi extends UmbTiptapToolbarElementApiBase {
+ override isActive(editor?: Editor, item?: MetaTiptapToolbarMenuItem) {
+ const styles = editor?.getAttributes('span')?.style;
+ return styles?.includes(`font-size: ${item?.data};`) === true;
+ }
+
override execute(editor?: Editor, item?: MetaTiptapToolbarMenuItem) {
if (!item?.data) return;
editor?.chain().focus().toggleSpanStyle(`font-size: ${item.data};`).run();
diff --git a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/types.ts b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/types.ts
index 7b2f40033cb5..68d57116931a 100644
--- a/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/types.ts
+++ b/src/Umbraco.Web.UI.Client/src/packages/tiptap/extensions/types.ts
@@ -54,7 +54,7 @@ export interface UmbTiptapToolbarElementApi extends UmbApi, UmbTiptapExtensionAr
/**
* Checks if the toolbar element is active.
*/
- isActive(editor?: Editor): boolean;
+ isActive(editor?: Editor, ...args: Array): boolean;
/**
* Checks if the toolbar element is disabled.