diff --git a/libs/features/icons/icons.js b/libs/features/icons/icons.js
index a39ff61e06..297e044728 100644
--- a/libs/features/icons/icons.js
+++ b/libs/features/icons/icons.js
@@ -39,23 +39,6 @@ export const fetchIcons = (config) => new Promise(async (resolve) => {
resolve(fetchedIcons);
});
-async function decorateToolTip(icon) {
- const wrapper = icon.closest('em');
- if (!wrapper) return;
- wrapper.className = 'tooltip-wrapper';
- const conf = wrapper.textContent.split('|');
- // Text is the last part of a tooltip
- const content = conf.pop().trim();
- if (!content) return;
- icon.dataset.tooltip = content;
- // Position is the next to last part of a tooltip
- const place = conf.pop()?.trim().toLowerCase() || 'right';
- const defaultIcon = 'info-outline';
- icon.className = `icon icon-${defaultIcon} milo-tooltip ${place}`;
- icon.dataset.name = defaultIcon;
- wrapper.parentElement.replaceChild(icon, wrapper);
-}
-
export function getIconData(icon) {
const fedRoot = getFederatedContentRoot();
const name = [...icon.classList].find((c) => c.startsWith('icon-'))?.substring(5);
@@ -87,8 +70,15 @@ function filterDuplicatedIcons(icons) {
return uniqueIcons;
}
-export async function decorateIcons(area, icons, config) {
+export function handleLegacyToolTip(icons, iconClass = 'icon-info-outline') {
+ const tooltips = [...icons].filter((icon) => icon.classList.contains('icon-tooltip'));
+ if (!tooltips.length) return;
+ tooltips.forEach((icon) => icon.classList.replace('icon-tooltip', iconClass));
+}
+
+export async function decorateIcons(icons, config) {
if (!icons.length) return;
+ handleLegacyToolTip(icons);
const uniqueIcons = filterDuplicatedIcons(icons);
if (!uniqueIcons.length) return;
preloadInViewIcons(uniqueIcons);
@@ -106,8 +96,9 @@ export default async function loadIcons(icons) {
const iconsToFetch = new Map();
icons.forEach(async (icon) => {
- const isToolTip = icon.classList.contains('icon-tooltip');
- if (isToolTip) decorateToolTip(icon);
+ if (icon.dataset.tooltip) {
+ icon.classList.add('milo-tooltip', icon.dataset.tooltipdir);
+ }
const iconName = icon.dataset.name;
if (icon.dataset.svgInjected || !iconName) return;
if (!federalIcons[iconName] && !iconsToFetch.has(iconName)) {
diff --git a/libs/utils/utils.js b/libs/utils/utils.js
index c29960c7de..5e3ff48381 100644
--- a/libs/utils/utils.js
+++ b/libs/utils/utils.js
@@ -793,9 +793,11 @@ const findReplaceableNodes = (area) => {
let matchFound = false;
if (node.nodeType === Node.TEXT_NODE) {
matchFound = regex.test(node.nodeValue);
- } else if (node.nodeType === Node.ELEMENT_NODE && node.hasAttribute('href')) {
- const hrefValue = node.getAttribute('href');
- matchFound = regex.test(hrefValue);
+ } else if (node.nodeType === Node.ELEMENT_NODE) {
+ const attr = node.getAttribute('href') || node.getAttribute('data-tooltip');
+ if (attr) {
+ matchFound = regex.test(attr);
+ }
}
if (matchFound) {
nodes.push(node);
@@ -1250,8 +1252,15 @@ async function resolveInlineFrags(section) {
section.preloadLinks = newlyDecoratedSection.preloadLinks;
}
-export function setIconsIndexClass(icons) {
+export function setIconAttrs(icons) {
[...icons].forEach((icon) => {
+ const em = icon.closest('em');
+ const conf = em?.textContent.split('|');
+ if (em && conf.length) {
+ icon.dataset.tooltip = conf?.pop()?.trim();
+ icon.dataset.tooltipdir = conf?.pop()?.trim().toLowerCase() || 'right';
+ em.parentElement.replaceChild(icon, em);
+ }
const parent = icon.parentNode;
const children = parent.childNodes;
const nodeIndex = [...children].indexOf.call(children, icon);
@@ -1303,7 +1312,7 @@ export async function loadArea(area = document) {
const allIcons = area.querySelectorAll('span.icon');
if (allIcons.length) {
- setIconsIndexClass(allIcons);
+ setIconAttrs(allIcons);
}
const sections = decorateSections(area, isDoc);
@@ -1320,7 +1329,7 @@ export async function loadArea(area = document) {
if (allIcons.length) {
const { default: loadIcons, decorateIcons } = await import('../features/icons/icons.js');
- await decorateIcons(area, allIcons, config);
+ await decorateIcons(allIcons, config);
await loadIcons(allIcons);
}
diff --git a/test/features/icons/icons.test.js b/test/features/icons/icons.test.js
index cb3cb994db..0687086d1d 100644
--- a/test/features/icons/icons.test.js
+++ b/test/features/icons/icons.test.js
@@ -1,10 +1,10 @@
import { readFile } from '@web/test-runner-commands';
import { expect } from '@esm-bundle/chai';
-import sinon, { stub } from 'sinon';
+import { stub } from 'sinon';
import { waitForElement } from '../../helpers/waitfor.js';
-const { default: loadIcons, getIconData } = await import('../../../libs/features/icons/icons.js');
-const { setIconsIndexClass } = await import('../../../libs/utils/utils.js');
+const { default: loadIcons, getIconData, handleLegacyToolTip } = await import('../../../libs/features/icons/icons.js');
+const { setIconAttrs } = await import('../../../libs/utils/utils.js');
const mockRes = ({ payload, status = 200, ok = true } = {}) => new Promise((resolve) => {
resolve({
status,
@@ -22,33 +22,32 @@ const svgEx = `
This is text w/ an in the middle of the paragraph.
| This is my tooltip text.
| top | This is my tooltip text.
+| left | This is my tooltip text.