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

Truck features #43 #155

Merged
merged 24 commits into from
Nov 17, 2023
Merged
Show file tree
Hide file tree
Changes from 18 commits
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
211 changes: 211 additions & 0 deletions blocks/v2-truck-features/v2-truck-features.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
.section.v2-truck-features-container > .v2-truck-features-wrapper {
padding: 0;
}

.v2-truck-features {
padding: 0;
color: var(--text-color);
}

.v2-truck-features__content {
width: 100%;
height: calc(100vh - var(--nav-height) - var(--inpage-navigation-height));
cogniSyb marked this conversation as resolved.
Show resolved Hide resolved
position: sticky;
top: calc(var(--nav-height) + var(--inpage-navigation-height));
display: flex;
flex-direction: column;
align-items: flex-start;
}

.v2-truck-features__heading {
font-family: var(--ff-subheadings-medium);
font-size: 32px;
line-height: var(--headline-3-line-height);
margin: 0;
padding: 40px 16px;
}

.v2-truck-features__slides {
margin: 0;
list-style: none;
padding: 0;
}

.v2-truck-features ul ul:first-of-type {
display: none;
}

.v2-truck-features .v2-truck-features__images-list {
margin: 0;
padding: 0;
}

.v2-truck-features .v2-truck-features__images-list li {
display: none;
width: auto;
}

.v2-truck-features .v2-truck-features__slide {
display: none;
flex-direction: column;
gap: 8px;
}

.v2-truck-features .v2-truck-features__slide.v2-truck-features__slide--active {
display: flex;
flex-direction: column-reverse;
}

.v2-truck-features .v2-truck-features__slide h4 {
font-family: var(--ff-subheadings-medium);
line-height: var(--headline-5-line-height);
font-size: 18px;
letter-spacing: 0.36px;
margin: 0;
}

.v2-truck-features .v2-truck-features__slide h4::before {
width: 2px;
height: 27px;
content: '';
display: block;
position: absolute;
background: var(--c-primary-white);
left: 16px;
}

.v2-truck-features .v2-truck-features__slide p {
margin: 0;
}

.v2-truck-features .v2-truck-features__slide--active h4::before {
background: var(--c-accent-red);
}

.v2-truck-features
.v2-truck-features__images-list
li.v2-truck-features__slide-image--active {
display: flex;
justify-content: center;
}

.v2-truck-features__slide-image--active picture,
.v2-truck-features__slide-image--active img {
display: flex;
height: 275px;
aspect-ratio: 375/275;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where does this aspect ratio come from? The uploaded images have an aspect ratio of 845/498 and in the design I see a different sizing.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I took it from mobile design.
obraz
Because the images are different sizes and positioned in different ways I took the image frame aspect-ratio.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is updated

}

.v2-truck-features__text-wrapper {
position: relative;
align-self: flex-start;
padding: 24px 16px 24px 40px;
}

.v2-truck-features__text-wrapper a:any-link {
color: currentcolor;
text-decoration: underline;
text-decoration-color: var(--link-color);
}

@media (min-width: 768px) {
.v2-truck-features .v2-truck-features__heading {
width: 368px;
padding: 100px 0 0 32px;
}

.v2-truck-features .v2-truck-features__slides {
margin: 22px 0;
width: 368px;
}

.v2-truck-features .v2-truck-features__slide {
padding: 12px 0 12px 48px;
display: flex;
}

.v2-truck-features .v2-truck-features__slide h4::before {
height: calc(100% + 24px);
left: -16px;
top: -12px;
}

.v2-truck-features .v2-truck-features__text-wrapper {
padding: 0;
}

.v2-truck-features .v2-truck-features__text-wrapper p {
display: none;
}

.v2-truck-features .v2-truck-features__slide--active p {
display: block;
}

.v2-truck-features .v2-truck-features__images-list {
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
}

.v2-truck-features__slide-image--active::after {
content: '';
display: block;
height: 100%;
position: absolute;
background: radial-gradient(
52.65% 52.65% at 50% 56%,
#fff0 31.16%,
#dfdfdf 89.49%
);
width: 50vw;
max-width: 720px;
}

.v2-truck-features__slide-image--active picture,
.v2-truck-features__slide-image--active img {
width: 50vw;
max-width: 720px;
height: auto;
}

.v2-truck-features.v2-truck-features--image-left .v2-truck-features__content {
align-items: flex-end;
}

.v2-truck-features.v2-truck-features--image-left
.v2-truck-features__images-list {
left: 0;
right: unset;
}
}

@media (min-width: 1200px) {
.v2-truck-features {
--image-margin: calc((min(1440px, 100vw) - 1040px) / -2)
}

.v2-truck-features .v2-truck-features__slide {
padding-left: 36px;
}

.v2-truck-features__slide-image--active::after {
margin-right: var(--image-margin);
}

.v2-truck-features .v2-truck-features__slide-image--active picture {
margin-right: var(--image-margin);
}

.v2-truck-features.v2-truck-features--image-left picture {
margin-left: var(--image-margin);
margin-right: unset;
}

.v2-truck-features--image-left
.v2-truck-features__slide-image--active::after {
margin-left: var(--image-margin);
margin-right: unset;
}
}
178 changes: 178 additions & 0 deletions blocks/v2-truck-features/v2-truck-features.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
import {
createElement, debounce, unwrapDivs, variantsClassesToBEM,
} from '../../scripts/common.js';
import { getAllElWithChildren } from '../../scripts/scripts.js';

const blockName = 'v2-truck-features';
const desktopMQ = window.matchMedia('(min-width: 1200px)');
const SLIDE_SCROLL_PADDING_IN_PX = 100;

const selectImagesList = (slide) => {
const imagesLists = [...getAllElWithChildren(slide.querySelectorAll('ul'), ':scope > li > picture')];

if (imagesLists === 0) {
return;
}

imagesLists.forEach((el) => {
el.style.display = 'none';
});

const selectedImagesListIndex = desktopMQ.matches ? '-1' : '0';

imagesLists.at(selectedImagesListIndex).style.display = 'block';
imagesLists.at(selectedImagesListIndex).classList.add(`${blockName}__images-list`);
};

const setContentWrapperHeight = (wrapper, slidesCount) => {
const navHeight = getComputedStyle(document.documentElement).getPropertyValue('--nav-height');
const navHeightInPx = Number.parseInt(navHeight, 10); // assuming that the --nav-height is in px
const inPageNav = getComputedStyle(document.documentElement).getPropertyValue('--inpage-navigation-height');
// assuming that the --inpage-navigation-height is in px
const inPageNavInPx = Number.parseInt(inPageNav, 10);
const windowHeightInPx = window.innerHeight;
const availableViewportInPx = windowHeightInPx - navHeightInPx - inPageNavInPx;
// wrapper height is the viewport height without navigations
// (to make sure that the slide will fit inside the block) + scroll padding for every slide
const wrapperHeight = SLIDE_SCROLL_PADDING_IN_PX * slidesCount + availableViewportInPx;
wrapper.style.height = `${wrapperHeight}px`;
};

export default async function decorate(block) {
const activeSlideClass = `${blockName}__slide--active`;
const activeSlideImageClass = `${blockName}__slide-image--active`;
const variantClasses = ['image-left'];
variantsClassesToBEM(block.classList, variantClasses, blockName);

[...block.querySelectorAll(':scope > div')].forEach(unwrapDivs);

const heading = block.querySelector(':scope > div > :is(h1, h2, h3, h4, h5, h6)');
const rows = [...block.querySelectorAll(':scope > div')].slice(1);
const list = createElement('ul', { classes: `${blockName}__slides` });
const contentEl = createElement('div', { classes: `${blockName}__content` });

heading.parentElement.replaceWith(heading);
heading.classList.add(`${blockName}__heading`);

contentEl.append(heading, list);
block.append(contentEl);

// moving the rows to list
rows.forEach((el) => {
const newEl = createElement('li', { classes: `${blockName}__slide` });
const textWrapper = createElement('div', { classes: `${blockName}__text-wrapper` });

newEl.innerHTML = el.innerHTML;

const descriptionHeading = newEl.querySelector(':scope > :is(h1, h2, h3, h4, h5, h6)');
const description = newEl.querySelector(':scope > p');

descriptionHeading.replaceWith(textWrapper);
textWrapper.append(descriptionHeading, description);

el.remove();
list.append(newEl);
selectImagesList(newEl);
});

const slidesCount = list.querySelectorAll(`.${blockName}__images-list picture`).length;
setContentWrapperHeight(block, slidesCount);

// setting the first slide as active
let activeSlide = list.children[0];
activeSlide.classList.add(activeSlideClass);
// setting the first image in the first slide active
let activePicListItem = activeSlide.querySelector(`.${blockName}__images-list li`);
activePicListItem.classList.add(activeSlideImageClass);

const showNextSlide = () => {
const nextImageInSlide = block.querySelector(`.${activeSlideImageClass} + li`);
let hasNextSlide = true;

// if there is a next image in the same slide just switch image
if (nextImageInSlide) {
activePicListItem.classList.remove(activeSlideImageClass);
nextImageInSlide.classList.add(activeSlideImageClass);
activePicListItem = nextImageInSlide;
} else {
// if no next image in slide switch to next slide
const nextSlide = block.querySelector(`.${activeSlideClass} + li`);

if (nextSlide) {
activeSlide.classList.remove(activeSlideClass);
nextSlide.classList.add(activeSlideClass);
activeSlide = nextSlide;

activePicListItem.classList.remove(activeSlideImageClass);
activePicListItem = nextSlide.querySelector(`.${blockName}__images-list li`);
activePicListItem.classList.add(activeSlideImageClass);
} else {
hasNextSlide = false;
}
}

return hasNextSlide;
};

const showPrevSlide = () => {
const prevImageInSlide = block.querySelector(`.${activeSlideImageClass}`).previousElementSibling;
let hasPrevSlide = true;

// if there is a prev image in the same slide just switch image
if (prevImageInSlide) {
activePicListItem.classList.remove(activeSlideImageClass);
prevImageInSlide.classList.add(activeSlideImageClass);
activePicListItem = prevImageInSlide;
} else {
// if no prev image in slide switch to prev slide
const prevSlide = block.querySelector(`.${activeSlideClass}`).previousElementSibling;

if (prevSlide) {
activeSlide.classList.remove(activeSlideClass);
prevSlide.classList.add(activeSlideClass);
activeSlide = prevSlide;

activePicListItem.classList.remove(activeSlideImageClass);
activePicListItem = prevSlide.querySelector(`.${blockName}__images-list li:last-of-type`);
activePicListItem.classList.add(activeSlideImageClass);
} else {
hasPrevSlide = false;
}
}

return hasPrevSlide;
};

let slideIndex = 0;

window.addEventListener('scroll', debounce(() => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TomaszDziezykNetcentric The snapping function doesn't work properly. Because of debounce the values inside the function are not precise. I suggest removing debouncing.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

debouce removed

const navHeight = getComputedStyle(document.documentElement).getPropertyValue('--nav-height');
const navHeightInPx = Number.parseInt(navHeight, 10); // assuming that the --nav-height is in px
const inPageNav = getComputedStyle(document.documentElement).getPropertyValue('--inpage-navigation-height');
// assuming that the --inpage-navigation-height is in px
const inPageNavInPx = Number.parseInt(inPageNav, 10);
const { top: blockTopPosition, bottom: blockBottomPosition } = block.getBoundingClientRect();

if (
blockTopPosition < navHeightInPx + inPageNavInPx
&& blockBottomPosition > navHeightInPx + inPageNavInPx
) {
const blockScrollInPx = Math.abs(blockTopPosition - navHeightInPx - inPageNavInPx);
const newSlideIndex = Math.floor(blockScrollInPx / SLIDE_SCROLL_PADDING_IN_PX);

if (newSlideIndex > slidesCount) {
return;
}

if (newSlideIndex > slideIndex) {
showNextSlide();
}

if (newSlideIndex < slideIndex) {
showPrevSlide();
}

slideIndex = newSlideIndex;
}
}, 10));
}
2 changes: 1 addition & 1 deletion styles/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -866,7 +866,7 @@ main .section.responsive-title h1 {
--easing-standard: cubic-bezier(0.2, 0, 0.1, 1);

/* In page navigation */
--inpage-navigation-height: 0;
--inpage-navigation-height: 0px;
}

.redesign-v2 body {
Expand Down