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

[Release] Stage to Main #3355

Merged
merged 11 commits into from
Jan 2, 2025
Merged
Changes from 1 commit
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
Prev Previous commit
Next Next commit
Revert "MWPW-140452 - Icon authoring in milo using the federal repo a…
…nd individual SVG assets" (#3356)

Revert "MWPW-140452 - Icon authoring in milo using the federal repo and indiv…"

This reverts commit 81a5770.
  • Loading branch information
mokimo authored Dec 11, 2024
commit 0052f31e8b1a815199bd6130f8dd629a82e691cf
1 change: 0 additions & 1 deletion libs/blocks/table/table.css
Original file line number Diff line number Diff line change
@@ -360,7 +360,6 @@
width: 15px;
height: 15px;
cursor: pointer;
margin-inline: unset;
}

.table .section-head-title:hover .icon.expand {
7 changes: 6 additions & 1 deletion libs/blocks/text/text.css
Original file line number Diff line number Diff line change
@@ -100,7 +100,7 @@
position: relative;
}

.text-block .icon-list-item .icon.node-index-first {
.text-block .icon-list-item .icon.margin-right:not(.margin-left) { /* target first node only */
position: absolute;
inset: 0 100% auto auto;
}
@@ -122,6 +122,7 @@

.text-block .icon-area {
display: flex;
column-gap: var(--spacing-xs);
}

.text-block p.icon-area { /* NOT <a/> tags with icons in them */
@@ -217,6 +218,10 @@
max-width: unset;
}

.text-block .icon-area.con-button {
column-gap: unset;
}

.text-block .icon-area picture {
line-height: 0em;
height: inherit; /* Safari + FF bug fix */
1 change: 0 additions & 1 deletion libs/features/georoutingv2/georoutingv2.css
Original file line number Diff line number Diff line change
@@ -83,7 +83,6 @@
}

.dialog-modal.locale-modal-v2 span.icon {
display: inline;
vertical-align: middle;
}

2 changes: 1 addition & 1 deletion libs/features/georoutingv2/georoutingv2.js
Original file line number Diff line number Diff line change
@@ -194,7 +194,7 @@ function buildContent(currentPage, locale, geoData, locales) {
{ once: true },
);
img.src = `${config.miloLibs || config.codeRoot}/img/georouting/${flagFile}`;
const span = createTag('span', { class: 'icon node-index-first' }, img);
const span = createTag('span', { class: 'icon margin-inline-end' }, img);
const mainAction = createTag('a', {
class: 'con-button blue button-l', lang, role: 'button', 'aria-haspopup': !!locales, 'aria-expanded': false, href: '#',
}, span);
2 changes: 1 addition & 1 deletion libs/features/icons/icons.css
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@
border-bottom: none;
}

.milo-tooltip::before {
.milo-tooltip::before {
content: attr(data-tooltip);
position: absolute;
top: 50%;
118 changes: 21 additions & 97 deletions libs/features/icons/icons.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { getFederatedContentRoot } from '../../utils/federated.js';
import { loadLink, loadStyle } from '../../utils/utils.js';

let fetchedIcons;
let fetched = false;
const federalIcons = {};

async function getSVGsfromFile(path) {
/* c8 ignore next */
@@ -26,7 +22,6 @@ async function getSVGsfromFile(path) {
return miloIcons;
}

// TODO: remove after all consumers have stopped calling this method
// eslint-disable-next-line no-async-promise-executor
export const fetchIcons = (config) => new Promise(async (resolve) => {
/* c8 ignore next */
@@ -39,112 +34,41 @@ export const fetchIcons = (config) => new Promise(async (resolve) => {
resolve(fetchedIcons);
});

async function decorateToolTip(icon) {
function decorateToolTip(icon) {
const wrapper = icon.closest('em');
if (!wrapper) return;
wrapper.className = 'tooltip-wrapper';
if (!wrapper) return;
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;
icon.className = `icon icon-info milo-tooltip ${place}`;
wrapper.parentElement.replaceChild(icon, wrapper);
}

export function getIconData(icon) {
const fedRoot = getFederatedContentRoot();
const name = [...icon.classList].find((c) => c.startsWith('icon-'))?.substring(5);
const path = `${fedRoot}/federal/assets/icons/svgs/${name}.svg`;
return { path, name };
}

function preloadInViewIconResources(config) {
const { base } = config;
loadStyle(`${base}/features/icons/icons.css`);
}

const preloadInViewIcons = async (icons = []) => icons.forEach((icon) => {
const { path } = getIconData(icon);
loadLink(path, { rel: 'preload', as: 'fetch', crossorigin: 'anonymous' });
});

function filterDuplicatedIcons(icons) {
if (!icons.length) return [];
const uniqueIconKeys = new Set();
const uniqueIcons = [];
for (const icon of icons) {
const key = [...icon.classList].find((c) => c.startsWith('icon-'))?.substring(5);
if (!uniqueIconKeys.has(key)) {
uniqueIconKeys.add(key);
uniqueIcons.push(icon);
}
}
return uniqueIcons;
}

export async function decorateIcons(area, icons, config) {
if (!icons.length) return;
const uniqueIcons = filterDuplicatedIcons(icons);
if (!uniqueIcons.length) return;
preloadInViewIcons(uniqueIcons);
preloadInViewIconResources(config);
icons.forEach((icon) => {
const iconName = [...icon.classList].find((c) => c.startsWith('icon-'))?.substring(5);
if (!iconName) return;
icon.dataset.name = iconName;
});
}

export default async function loadIcons(icons) {
const fedRoot = getFederatedContentRoot();
const iconRequests = [];
const iconsToFetch = new Map();

export default async function loadIcons(icons, config) {
const iconSVGs = await fetchIcons(config);
if (!iconSVGs) return;
icons.forEach(async (icon) => {
const isToolTip = icon.classList.contains('icon-tooltip');
if (isToolTip) decorateToolTip(icon);
const iconName = icon.dataset.name;
if (icon.dataset.svgInjected || !iconName) return;
if (!federalIcons[iconName] && !iconsToFetch.has(iconName)) {
const url = `${fedRoot}/federal/assets/icons/svgs/${iconName}.svg`;
iconsToFetch.set(iconName, fetch(url)
.then(async (res) => {
if (!res.ok) throw new Error(`Failed to fetch SVG for ${iconName}: ${res.statusText}`);
const text = await res.text();
const parser = new DOMParser();
const svgDoc = parser.parseFromString(text, 'image/svg+xml');
const svgElement = svgDoc.querySelector('svg');
if (!svgElement) {
window.lana?.log(`No SVG element found in fetched content for ${iconName}`);
return;
}
const svgClone = svgElement.cloneNode(true);
svgClone.classList.add('icon-milo', `icon-milo-${iconName}`);
federalIcons[iconName] = svgClone;
})
/* c8 ignore next 3 */
.catch((error) => {
window.lana?.log(`Error fetching SVG for ${iconName}:`, error);
}));
}
iconRequests.push(iconsToFetch.get(iconName));
const { classList } = icon;
if (classList.contains('icon-tooltip')) decorateToolTip(icon);
const iconName = icon.classList[1].replace('icon-', '');
const existingIcon = icon.querySelector('svg');
if (!iconSVGs[iconName] || existingIcon) return;
const parent = icon.parentElement;
if (parent && parent.parentElement.tagName === 'LI') parent.parentElement.classList.add('icon-list-item');
});

await Promise.all(iconRequests);

icons.forEach((icon) => {
const iconName = icon.dataset.name;
if (iconName && federalIcons[iconName] && !icon.dataset.svgInjected) {
const svgClone = federalIcons[iconName].cloneNode(true);
icon.appendChild(svgClone);
icon.dataset.svgInjected = 'true';
if (parent.childNodes.length > 1) {
if (parent.lastChild === icon) {
icon.classList.add('margin-inline-start');
} else if (parent.firstChild === icon) {
icon.classList.add('margin-inline-end');
if (parent.parentElement.tagName === 'LI') parent.parentElement.classList.add('icon-list-item');
} else {
icon.classList.add('margin-inline-start', 'margin-inline-end');
}
}
icon.insertAdjacentHTML('afterbegin', iconSVGs[iconName].outerHTML);
});
}
30 changes: 11 additions & 19 deletions libs/styles/styles.css
Original file line number Diff line number Diff line change
@@ -128,7 +128,6 @@
--icon-size-s: 32px;
--icon-size-xs: 24px;
--icon-size-xxs: 16px;
--icon-spacing: 8px;

/* z-index */
--above-all: 9000; /* Used for page tools that overlay page content */
@@ -350,7 +349,6 @@
line-height: 20px;
min-height: 21px;
padding: 7px 18px 8px;
--icon-spacing: 12px;
}

.xl-button .con-button,
@@ -360,7 +358,6 @@
line-height: 24px;
min-height: 28px;
padding: 10px 24px 8px;
--icon-spacing: 14px;
}

.xxl-button .con-button,
@@ -370,7 +367,6 @@
line-height: 27px;
min-height: 27px;
padding: 14px 30px 15px;
--icon-spacing: 14px;
}

.con-button.button-justified {
@@ -563,23 +559,19 @@ div[data-failed="true"]::before {
color: var(--color-gray-300);
}

span.icon {
width: 1em;
display: inline-block;
margin-inline: var(--icon-spacing);
}
span.icon.margin-right { margin-right: 8px; }

span.icon.node-index-first { margin-inline-start: unset; }
span.icon.node-index-middle { margin-inline: var(--icon-spacing); }
span.icon.node-index-last { margin-inline-end: unset; }
span.icon.node-index-only { margin-inline: unset; }
span.icon.margin-left { margin-left: 8px; }

span.icon svg {
height: 1em;
position: relative;
top: .1em;
width: auto;
}
span.icon.margin-inline-end { margin-inline-end: 8px; }

span.icon.margin-inline-start { margin-inline-start: 8px; }

.button-l .con-button span.icon.margin-left,
.con-button.button-l span.icon.margin-left { margin-left: 12px; }

.button-xl .con-button span.icon.margin-left,
.con-button.button-xl span.icon.margin-left { margin-left: 14px; }

/* Con Block Utils */
.con-block.xs-spacing { padding: var(--spacing-xs) 0; }
43 changes: 15 additions & 28 deletions libs/utils/utils.js
Original file line number Diff line number Diff line change
@@ -790,6 +790,16 @@ function decorateHeader() {
if (promo?.length) header.classList.add('has-promo');
}

async function decorateIcons(area, config) {
const icons = area.querySelectorAll('span.icon');
if (icons.length === 0) return;
const { base } = config;
loadStyle(`${base}/features/icons/icons.css`);
loadLink(`${base}/img/icons/icons.svg`, { rel: 'preload', as: 'fetch', crossorigin: 'anonymous' });
const { default: loadIcons } = await import('../features/icons/icons.js');
await loadIcons(icons, config);
}

export async function customFetch({ resource, withCacheRules }) {
const options = {};
if (withCacheRules) {
@@ -1266,8 +1276,9 @@ function decorateDocumentExtras() {
decorateHeader();
}

async function documentPostSectionLoading(area, config) {
async function documentPostSectionLoading(config) {
decorateFooterPromo();

const appendage = getMetadata('title-append');
if (appendage) {
import('../features/title-append/title-append.js').then((module) => module.default(appendage));
@@ -1331,25 +1342,14 @@ async function resolveInlineFrags(section) {
section.preloadLinks = newlyDecoratedSection.preloadLinks;
}

export function setIconsIndexClass(icons) {
[...icons].forEach((icon) => {
const parent = icon.parentNode;
const children = parent.childNodes;
const nodeIndex = [...children].indexOf.call(children, icon);
let indexClass = (nodeIndex === children.length - 1) ? 'last' : 'middle';
if (nodeIndex === 0) indexClass = 'first';
if (children.length === 1) indexClass = 'only';
icon.classList.add(`node-index-${indexClass}`);
});
}

async function processSection(section, config, isDoc) {
await resolveInlineFrags(section);
const firstSection = section.el.dataset.idx === '0';
const stylePromises = firstSection ? preloadBlockResources(section.blocks) : [];
preloadBlockResources(section.preloadLinks);
await Promise.all([
decoratePlaceholders(section.el, config),
decorateIcons(section.el, config),
]);
const loadBlocks = [...stylePromises];
if (section.preloadLinks.length) {
@@ -1382,11 +1382,6 @@ export async function loadArea(area = document) {
decorateDocumentExtras();
}

const allIcons = area.querySelectorAll('span.icon');
if (allIcons.length) {
setIconsIndexClass(allIcons);
}

const sections = decorateSections(area, isDoc);

const areaBlocks = [];
@@ -1399,21 +1394,13 @@ export async function loadArea(area = document) {
});
}

if (allIcons.length) {
const { default: loadIcons, decorateIcons } = await import('../features/icons/icons.js');
const areaIcons = area.querySelectorAll('span.icon');
await decorateIcons(area, areaIcons, config);
await loadIcons(areaIcons);
}

const currentHash = window.location.hash;
if (currentHash) {
scrollToHashedElement(currentHash);
}

if (isDoc) {
await documentPostSectionLoading(area, config);
}
if (isDoc) await documentPostSectionLoading(config);

await loadDeferred(area, areaBlocks, config);
}

Loading
Loading