Skip to content

Commit

Permalink
Merge pull request #66 from Netcentric/26-in-page-nav-pdp
Browse files Browse the repository at this point in the history
26 in page nav pdp
  • Loading branch information
Lakshmishri authored Sep 4, 2023
2 parents 4f13840 + d7db84f commit 895686b
Show file tree
Hide file tree
Showing 6 changed files with 530 additions and 0 deletions.
208 changes: 208 additions & 0 deletions blocks/v2-inpage-navigation/v2-inpage-navigation.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
:root {
--inpage-navigation-height: 48px;
}

.v2-inpage-navigation-wrapper {
background-color: var(--c-primary-white);
box-shadow: 0 4px 24px 0 rgb(0 0 0 / 16%);
height: auto !important;
left: 0;
overflow: unset !important;
position: sticky;
top: var(--nav-height);
width: 100%;
z-index: 2;
}

.v2-inpage-navigation__wrapper {
display: flex;
margin: 0 auto;
}

.v2-inpage-navigation__dropdown {
flex-grow: 1;
position: relative;
}

.v2-inpage-navigation__items {
background-color: var(--c-primary-white);
box-shadow: 0 4px 24px 0 rgb(0 0 0 / 16%);
display: none;
left: 0;
list-style: none;
margin: 0;
padding: 0;
position: absolute;
top: 100%;
width: 100%;
z-index: -1;
}

.v2-inpage-navigation__item--active {
display: none;
}

.v2-inpage-navigation__item button,
.v2-inpage-navigation__selected-item-wrapper {
background: none;
border: 0;
color: var(--c-primary-black);
cursor: pointer;
display: block;
font-family: var(--ff-body-bold);
font-size: var(--body-2-font-size);
line-height: var(--body-2-line-height);
margin: 0;
padding: 14px 24px;
width: 100%;
}

/* stylelint-disable-next-line no-descending-specificity */
.v2-inpage-navigation__item button:hover,
.v2-inpage-navigation__item button:active,
.v2-inpage-navigation__item button:focus,
.v2-inpage-navigation__selected-item-wrapper:hover,
.v2-inpage-navigation__selected-item-wrapper:active
.v2-inpage-navigation__selected-item-wrapper:focus,
.v2-inpage-navigation__dropdown--open .v2-inpage-navigation__selected-item-wrapper {
background-color: #F1F1F1;
}

/* stylelint-disable-next-line no-descending-specificity */
.v2-inpage-navigation__item button {
max-width: none;
text-align: left;
}

/* stylelint-disable-next-line no-descending-specificity */
.v2-inpage-navigation__selected-item-wrapper {
display: flex;
justify-content: space-between;
align-items: center;
}

.v2-inpage-navigation__selected-item-wrapper svg {
--color-icon: var(--c-accent-red);

height: 16px;
transition: transform var(--duration-small) var(--easing-standard);
width: 16px;
}

/* Customization when dropdown is open */
.v2-inpage-navigation__dropdown--open .v2-inpage-navigation__items {
display: block;
}

.v2-inpage-navigation__dropdown--open .v2-inpage-navigation__selected-item-wrapper svg {
transform: rotate(180deg);
}

/* END Customization when dropdown is open */

/* Red button */
.v2-inpage-navigation__cta:any-link {
align-items: center;
background-color: var(--button-primary-red-enabled);
color: var(--c-primary-white);
display: flex;
font-family: var(--ff-body);
font-size: 14px;
font-style: normal;
font-weight: 500;
letter-spacing: 1.12px;
line-height: 18px;
padding: 0 20px;
text-decoration: none;
}

.v2-inpage-navigation__cta:hover,
.v2-inpage-navigation__cta:focus {
background-color: var(--button-primary-red-hover);
}

.v2-inpage-navigation__cta:active {
background-color: var(--button-primary-red-pressed);
}

.v2-inpage-navigation__cta--desktop {
display: none;
}

@media (min-width: 1200px) {
:root {
--inpage-navigation-height: 96px;
}

.v2-inpage-navigation__wrapper {
align-items: center;
gap: 24px;
max-width: var(--wrapper-width);
padding: 24px 0;
}

.v2-inpage-navigation__selected-item-wrapper {
display: none;
}

.v2-inpage-navigation__items,
.v2-inpage-navigation__dropdown--open .v2-inpage-navigation__items {
display: flex;
}

/* stylelint-disable-next-line no-descending-specificity */
.v2-inpage-navigation__items {
box-shadow: none;
gap: 24px;
justify-content: space-between;
position: unset;
}

.v2-inpage-navigation__item {
margin-right: auto;
}

.v2-inpage-navigation__item--active {
display: block;
}

.v2-inpage-navigation__item button {
padding: 10px 0;
position: relative;
}

.v2-inpage-navigation__item button:hover,
.v2-inpage-navigation__item button:focus {
background: none;
}

.v2-inpage-navigation__item button::after {
bottom: 0;
content: '';
display: block;
height: 4px;
position: absolute;
transition: background-color var(--duration-small) var(--easing-standard);
width: 100%;
}

.v2-inpage-navigation__item--active button::after,
.v2-inpage-navigation__item button:hover::after,
.v2-inpage-navigation__item button:focus::after {
background-color: var(--c-accent-red);
}

/* Red button */
.v2-inpage-navigation__cta:any-link {
border-radius: 2px;
padding: 15px 20px;
}

.v2-inpage-navigation__cta--mobile {
display: none;
}

.v2-inpage-navigation__cta--desktop {
display: block;
}
}
185 changes: 185 additions & 0 deletions blocks/v2-inpage-navigation/v2-inpage-navigation.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
import { getMetadata } from '../../scripts/lib-franklin.js';
import { createElement } from '../../scripts/common.js';

const blockName = 'v2-inpage-navigation';

const scrollToSection = (id) => {
let timeout;

const container = document.querySelector(`main .section[data-inpageid='${id}']`);
container?.scrollIntoView({ behavior: 'smooth' });

// Checking if the height of the main element changes while scrolling (caused by layout shift)
const main = document.querySelector('main');
const resizeObserver = new ResizeObserver(() => {
clearTimeout(timeout);
container?.scrollIntoView({ behavior: 'smooth' });

timeout = setTimeout(() => {
resizeObserver.disconnect();
}, 500);
});
resizeObserver.observe(main);
};

const inpageNavigationRedButton = () => {
// if we have a button title & button link
if (getMetadata('inpage-button') && getMetadata('inpage-link')) {
const titleMobile = getMetadata('inpage-button');
const url = getMetadata('inpage-link');
const link = createElement('a', {
classes: `${blockName}__cta`,
props: {
href: url,
title: titleMobile,
},
});
const mobileText = createElement('span', { classes: `${blockName}__cta--mobile` });
mobileText.textContent = titleMobile;
link.appendChild(mobileText);

const titleDesktop = getMetadata('inpage-button-large');
if (titleDesktop) {
const desktopText = createElement('span', { classes: `${blockName}__cta--desktop` });
desktopText.textContent = titleDesktop;
link.setAttribute('title', titleDesktop);
link.appendChild(desktopText);
}

return link;
}

return null;
};

const gotoSection = (event) => {
const { target } = event;
const button = target.closest('button');

if (button) {
const { id } = button.dataset;

scrollToSection(id);
}
};

const updateActive = (id) => {
const activeItemInList = document.querySelector(`.${blockName}__item--active`);

// Prevent reassign active value
if (activeItemInList?.firstElementChild?.dataset.id === id) return;

// Remove focus position
document.activeElement.blur();

// check active id is equal to id dont do anything
const selectedItem = document.querySelector(`.${blockName}__selected-item`);
activeItemInList?.classList.remove(`${blockName}__item--active`);
const itemsButton = document.querySelectorAll(`.${blockName}__items button`);
const { pathname } = window.location;

if (id) {
const selectedButton = [...itemsButton].find((button) => button.dataset.id === id);
if (!selectedButton) return;
selectedItem.textContent = selectedButton.textContent;
selectedButton.parentNode.classList.add(`${blockName}__item--active`);

window.history.replaceState({}, '', `${pathname}#${id}`);
} else {
window.history.replaceState({}, '', `${pathname}`);
}
};

const listenScroll = () => {
let timeout;
const elements = document.querySelectorAll('main .section');

const io = new IntersectionObserver((entries) => {
// Reduce entries to the one with higher intersectionRatio
const intersectedEntry = entries.reduce((prev, current) => (
prev.intersectionRatio > current.intersectionRatio ? prev : current
));

if (intersectedEntry.isIntersecting && intersectedEntry.target.dataset?.inpageid) {
clearTimeout(timeout);

// wait to update the active item
timeout = setTimeout(() => {
updateActive(intersectedEntry.target.dataset.inpageid);
}, 500);
} else {
updateActive();
}
}, {
threshold: [0.2, 0.5, 0.7, 1],
});

elements.forEach((el) => {
io.observe(el);
});
};

export default async function decorate(block) {
const redButton = inpageNavigationRedButton();

const wrapper = block.querySelector(':scope > div');
wrapper.classList.add(`${blockName}__wrapper`);
const itemsWrapper = block.querySelector(':scope > div > div');

const dropdownWrapper = createElement('div', { classes: `${blockName}__dropdown` });
const selectedItemWrapper = createElement('div', { classes: `${blockName}__selected-item-wrapper` });
const selectedItem = createElement('div', { classes: `${blockName}__selected-item` });

const list = createElement('ul', { classes: `${blockName}__items` });

[...itemsWrapper.children].forEach((item, index) => {
const classes = [`${blockName}__item`];
if (index === 0) { // Default selected item
classes.push(`${blockName}__item--active`);
selectedItem.textContent = item.textContent;
}
const listItem = createElement('li', { classes });

listItem.innerHTML = item.innerHTML;
list.appendChild(listItem);
});

const dropdownArrowIcon = document.createRange().createContextualFragment(`
<svg xmlns="http://www.w3.org/2000/svg"><use href="#icons-sprite-dropdown-caret"></use></svg>`);
selectedItemWrapper.append(selectedItem);
selectedItemWrapper.appendChild(...dropdownArrowIcon.children);

dropdownWrapper.append(selectedItemWrapper);
dropdownWrapper.append(list);
wrapper.append(dropdownWrapper);

itemsWrapper.remove();

if (redButton) {
wrapper.appendChild(redButton);
}

list.addEventListener('click', gotoSection);

// on load Go to section if defined
const hash = window.location.hash.substring(1);
if (hash) {
updateActive(hash);

setTimeout(() => {
scrollToSection(hash);
}, 1000);
}

// Listener to toggle the dropdown (open / close)
document.addEventListener('click', (e) => {
if (e.target.closest(`.${blockName}__selected-item-wrapper`)) {
dropdownWrapper.classList.toggle(`${blockName}__dropdown--open`);
} else {
dropdownWrapper.classList.remove(`${blockName}__dropdown--open`);
}
});

// listen scroll to change the url
listenScroll();
}
Loading

0 comments on commit 895686b

Please sign in to comment.