Skip to content

Commit

Permalink
Main to Stage (#1861)
Browse files Browse the repository at this point in the history
* Mwpw 140539: merch card outline CTA hover state (#1851)

* outline cta merch card styles in dark section

* Update merch-card.js

* hover state outline cta

* Mwpw 142568: OST-generated Merch CTA text not displaying (#1858)

* MWPW-142568: OST-generated Merch CTA text not displaying

* MWPW-142568: OST-generated Merch CTA text not displaying

* Update merch.js

* MWPW-141291 - Icon-block (inline) - Icon and title should `align-items: center` (#1836)

* added conditional and style for items center

* remove console

* dark support, icon picture styles, no inline.items-center headline margins

* no em on 0 value, minor csslint fix

* MWPW-142003: Mini Compare Chart Merch Card UX observations (#1840)

* MWPW-142003: mini compare chart card UX observations

* nit fixes

* Updated dep with tacocat review comments

* intersection observer impl

* intersectionObserver comments

* review comments addressed

---------

Co-authored-by: Axel Cureno Basurto <[email protected]>
Co-authored-by: Ryan Parrish <[email protected]>
  • Loading branch information
3 people authored Feb 13, 2024
1 parent c05a022 commit 63be807
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 44 deletions.
27 changes: 23 additions & 4 deletions libs/blocks/icon-block/icon-block.css
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
position: relative;
}

.dark .icon-block,
.icon-block.dark {
color: #fff;
}

.icon-block p {
margin: 0;
}
Expand Down Expand Up @@ -66,11 +71,20 @@
overflow: hidden;
}

.icon-block .foreground .icon-area picture {
line-height: 0;
display: block;
}

.icon-block .foreground .icon-area img {
max-height: var(--icon-size-xxl);
width: auto;
}

.icon-block .foreground .text-content [class*="heading"] {
margin: 0 0 var(--spacing-xs);
}

.icon-block.inline .foreground {
max-width: max-content;
margin: 0 auto;
Expand All @@ -82,6 +96,14 @@
gap: 16px;
}

.icon-block.inline.items-center .foreground .text-content {
align-items: center;
}

.icon-block.inline.items-center .foreground .text-content [class*="heading"] {
margin-bottom: 0;
}

.icon-block.inline .body-s.action-area {
padding-top: 24px;
}
Expand Down Expand Up @@ -166,6 +188,7 @@

.icon-block.inline .foreground .text-content .icon-area {
width: fit-content;
display: contents;
}

.five-up .icon-block:not(.full-width) .foreground .icon-area img {
Expand Down Expand Up @@ -214,10 +237,6 @@
margin-bottom: var(--spacing-s);
}

.icon-block .foreground .text-content [class*="heading"] {
margin: 0 0 var(--spacing-xs);
}

.icon-block .foreground .text-content .action-area > a:last-child {
margin: 0;
}
Expand Down
1 change: 1 addition & 0 deletions libs/blocks/icon-block/icon-block.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ function decorateContent(el) {
textContent.forEach((content) => {
secondColumn.append(content);
});
if (secondColumn.children.length === 1) el.classList.add('items-center');
el.querySelector('.foreground .text-content').append(secondColumn);
}
}
Expand Down
6 changes: 6 additions & 0 deletions libs/blocks/merch-card/merch-card.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,9 @@ div[class*="-merch-card"] > div,
merch-card.special-offers del span[is="inline-price"] {
text-decoration: line-through;
}

.dark .merch-card .con-button.outline:hover {
color: var(--color-white);
background-color: var(--color-black);
text-decoration: none;
}
61 changes: 47 additions & 14 deletions libs/blocks/merch-card/merch-card.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,13 @@ const MINI_COMPARE_CHART = 'mini-compare-chart';

const MULTI_OFFER_CARDS = ['plans', 'product', MINI_COMPARE_CHART];
// Force cards to refresh once they become visible so that the footer rows are properly aligned.
const sectionObserver = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'attributes' && mutation.attributeName === 'data-status') {
const container = mutation.target.closest('main > div');
const intersectionObserver = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const container = entry.target.closest('main > div');
if (!container) return;
[...container.querySelectorAll('merch-card')].forEach((card) => card.requestUpdate());
intersectionObserver.unobserve(entry.target);
}
});
});
Expand All @@ -131,23 +132,40 @@ const getPodType = (styles) => styles?.find((style) => CARD_TYPES.includes(style
const isHeadingTag = (tagName) => /^H[2-5]$/.test(tagName);
const isParagraphTag = (tagName) => tagName === 'P';

const appendSlot = (slotEls, slotName, merchCard) => {
if (slotEls.length === 0) return;
const newEl = createTag(
'p',
{ slot: slotName, class: slotName },
);
slotEls.forEach((e, index) => {
newEl.innerHTML += e.innerHTML;
if (index < slotEls.length - 1) {
newEl.innerHTML += '<br>';
}
});
merchCard.append(newEl);
};

const parseContent = (el, merchCard) => {
const innerElements = [
...el.querySelectorAll('h2, h3, h4, h5, p, ul, em'),
];
let bodySlotName = 'body-xs';
let headingMCount = 0;

if (merchCard.variant === MINI_COMPARE_CHART) {
bodySlotName = 'body-m';
const promoText = el.querySelectorAll('h5');
const priceSmallType = el.querySelectorAll('h6');
appendSlot(promoText, 'promo-text', merchCard);
appendSlot(priceSmallType, 'price-commitment', merchCard);
}

const bodySlot = createTag('div', { slot: bodySlotName });

innerElements.forEach((element) => {
const { tagName } = element;
if (tagName === 'EM' && !element.querySelector('a')) {
const promoText = createTag('p', { class: 'promo-text' }, element.innerHTML);
element.replaceWith(promoText);
}
if (isHeadingTag(tagName)) {
let slotName = textStyles[tagName];
if (slotName) {
Expand All @@ -169,6 +187,7 @@ const parseContent = (el, merchCard) => {
merchCard.append(bodySlot);
}
});

if (merchCard.variant === MINI_COMPARE_CHART && merchCard.childNodes[1]) {
merchCard.insertBefore(bodySlot, merchCard.childNodes[1]);
}
Expand Down Expand Up @@ -281,8 +300,11 @@ function extractQuantitySelect(el) {
}

const getMiniCompareChartFooterRows = (el) => {
let footerRows = [];
footerRows = Array.from(el.children).slice(1);
let footerRows = Array.from(el.children).slice(1);
footerRows = footerRows.filter((row) => !row.querySelector('.footer-row-cell'));
if (footerRows[0].firstElementChild.innerText === 'Alt-cta') {
footerRows.splice(0, 2);
}
footerRows.forEach((row) => row.remove());
return footerRows;
};
Expand All @@ -306,6 +328,13 @@ const decorateFooterRows = (merchCard, footerRows) => {
}
};

const setMiniCompareOfferSlot = (merchCard, offers) => {
if (merchCard.variant !== MINI_COMPARE_CHART) return;
const miniCompareOffers = createTag('div', { slot: 'offers' }, offers);
if (offers === undefined) { miniCompareOffers.appendChild(createTag('p')); }
merchCard.appendChild(miniCompareOffers);
};

const init = async (el) => {
const styles = [...el.classList];
const lastClass = styles[styles.length - 1];
Expand Down Expand Up @@ -367,7 +396,7 @@ const init = async (el) => {
if (cardType === MINI_COMPARE_CHART) {
const container = el.closest('[data-status="decorated"]');
if (container) {
sectionObserver.observe(container, { attributes: true, subtree: false });
intersectionObserver.observe(container);
}
footerRows = getMiniCompareChartFooterRows(el);
}
Expand Down Expand Up @@ -447,14 +476,18 @@ const init = async (el) => {
if (MULTI_OFFER_CARDS.includes(cardType)) {
const quantitySelect = extractQuantitySelect(el);
const offerSelection = el.querySelector('ul');
const bodySlotName = `body-${merchCard.variant !== MINI_COMPARE_CHART ? 'xs' : 'm'}`;
if (offerSelection) {
const { initOfferSelection } = await import('./merch-offer-select.js');
setMiniCompareOfferSlot(merchCard, undefined);
initOfferSelection(merchCard, offerSelection, quantitySelect);
}
if (quantitySelect) {
const bodySlot = merchCard.querySelector(`div[slot="${bodySlotName}"]`);
bodySlot.append(quantitySelect);
if (merchCard.variant === MINI_COMPARE_CHART) {
setMiniCompareOfferSlot(merchCard, quantitySelect);
} else {
const bodySlot = merchCard.querySelector('div[slot="xs"]');
bodySlot.append(quantitySelect);
}
}
}

Expand Down
24 changes: 20 additions & 4 deletions libs/blocks/merch-card/merch-offer-select.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { createTag } from '../../utils/utils.js';
import { decorateButtons } from '../../utils/decorate.js';
import '../../deps/merch-offer-select.js';

const MINI_COMPARE_CHART = 'mini-compare-chart';

function createDynamicSlots(el, bodySlot) {
const pricePlaceholder = el.querySelector("span[is='inline-price']");
if (pricePlaceholder) {
Expand All @@ -17,8 +19,18 @@ function createDynamicSlots(el, bodySlot) {
const footer = el.querySelector('div[slot="footer"]');
footer.append(p);
bodySlot.querySelector('p')?.setAttribute('slot', 'description');
if (el.variant === MINI_COMPARE_CHART) {
const description = el.querySelector('div[slot="body-m"] p:last-child');
if (description) {
const descriptionSlot = el.querySelector('p[slot="description"]');
if (descriptionSlot) {
descriptionSlot.innerHTML += description.innerHTML;
}
}
}
}
function createMerchOffer(option, quantitySelector) {

function createMerchOffer(option, quantitySelector, variant) {
const merchOffer = createTag('merch-offer', { [quantitySelector ? 'value' : 'text']: option.childNodes[0].textContent.trim() });
[...option.querySelector('ul').children].forEach((li, index) => {
const override = li.childNodes[0];
Expand All @@ -34,19 +46,23 @@ function createMerchOffer(option, quantitySelector) {
merchOffer.append(override);
}
});
decorateButtons(merchOffer);
if (variant === MINI_COMPARE_CHART) {
decorateButtons(merchOffer, 'button-l');
} else {
decorateButtons(merchOffer);
}
return merchOffer;
}

const isHorizontal = (offerSelection) => [...offerSelection.querySelectorAll('merch-offer')].map((o) => o.text).every((t) => /^\d+.B$/.test(t));

export const initOfferSelection = (merchCard, offerSelection, quantitySelector) => {
const bodySlot = merchCard.querySelector('div[slot="body-xs"]');
const bodySlot = merchCard.querySelector(`div[slot="${merchCard.variant === 'mini-compare-chart' ? 'offers' : 'body-xs'}"]`);
if (!bodySlot) return;
createDynamicSlots(merchCard, bodySlot);
const merchOffers = createTag('merch-offer-select', { container: 'merch-card' });
[...offerSelection.children].forEach((option) => {
merchOffers.append(createMerchOffer(option, quantitySelector));
merchOffers.append(createMerchOffer(option, quantitySelector, merchCard.variant));
});
merchOffers.querySelectorAll('a[is="checkout-link"]').forEach((link) => { link.setAttribute('slot', 'cta'); });
if (isHorizontal(merchOffers)) {
Expand Down
4 changes: 0 additions & 4 deletions libs/blocks/merch/merch.css
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,6 @@ a[is='checkout-link'] > span {
min-width: 66px;
}

a[is='checkout-link'].loading-entitlements > span {
opacity: 0;
}

.price-unit-type:not(.disabled)::before,
.price-tax-inclusivity:not(.disabled)::before {
content: "\00a0";
Expand Down
Loading

0 comments on commit 63be807

Please sign in to comment.