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

Accordion column block #114 #203

Merged
merged 16 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
205 changes: 205 additions & 0 deletions blocks/v2-accordion-column/v2-accordion-column.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
.section > .v2-accordion-column-wrapper.full-width {
padding: 0 16px;
}

.v2-accordion-column__items-container {
margin: 40px 0 0;
}

.v2-accordion-column__header-container h2 {
font-family: var(--ff-headline-medium);
}

.v2-accordion-column__item-header-button {
background: transparent;
border: 0;
color: var(--c-primary-black);
display: flex;
justify-content: space-between;
margin: 0;
padding: 0 0 8px;
width: 100%;
cogniSyb marked this conversation as resolved.
Show resolved Hide resolved
}

.v2-accordion-column__item-header-button:hover,
.v2-accordion-column__item-header-button:focus {
background: transparent;
cursor: pointer;
}

.v2-accordion-column__item:not(.active) .v2-accordion-column__item-header-button {
padding: 0 0 12px;
}

.v2-accordion-column__item-title {
cogniSyb marked this conversation as resolved.
Show resolved Hide resolved
font-family: var(--ff-subheadings-medium);
font-size: var(--headline-4-font-size);
letter-spacing: var(--headline-1-letter-spacing);
line-height: var(--headline-1-line-height);
margin: 0;
}

.v2-accordion-column__close {
transform: rotate(0);
transition: transform var(--duration-small) var(--easing-standard);
}

.v2-accordion-column__item .icon svg {
height: 24px;
width: 24px;
}

.v2-accordion-column__item .icon svg,
.v2-accordion-column__item a .icon svg {
display: flex;
}

.v2-accordion-column__item a .icon svg {
height: 16px;
width: 16px;
stroke: currentcolor;
}

.v2-accordion-column__item.active .v2-accordion-column__close {
transform: rotate(180deg);
transition: transform var(--duration-small) var(--easing-standard);
}

.v2-accordion-column__item :is(
.v2-accordion-column__item-image,
.v2-accordion-column__item-description){
display: none;
}

.v2-accordion-column__item {
cogniSyb marked this conversation as resolved.
Show resolved Hide resolved
margin: 0 0 16px;
border-bottom: 1px solid var(--c-secondary-steel);
}

.v2-accordion-column__item.active {
margin: 40px 0;
display: flex;
flex-direction: column;
}

.v2-accordion-column__item.active :is(
.v2-accordion-column__item-image,
.v2-accordion-column__item-description) {
display: initial;
}

.v2-accordion-column__item-description .button-container .button {
align-items: stretch;
justify-content: flex-start;
gap: 4px;
margin: 0;
padding: 0;
border: 0;
background-color: transparent;
translate: none;
}

cogniSyb marked this conversation as resolved.
Show resolved Hide resolved
.v2-accordion-column__item-description {
padding: 0 0 24px;
}

.v2-accordion-column__item-description > p {
margin: 0;
padding: 16px 0 0;
}

.v2-accordion-column__item-description .button-container:hover .button svg,
.v2-accordion-column__item-description .button-container:focus-within .button svg{
translate: 3px;
transition: translate ease-out 0.2s;
}

.v2-accordion-column__item-image {
background-color: var(--c-primary-gray);
}

.v2-accordion-column__item-image img {
aspect-ratio: 16/10;
width: 100%;
height: auto;
cogniSyb marked this conversation as resolved.
Show resolved Hide resolved
display: block;
}
cogniSyb marked this conversation as resolved.
Show resolved Hide resolved

/* Left variant */
.v2-accordion-column--left .v2-accordion-column__item-image {
order: 1;
}

.v2-accordion-column--left .v2-accordion-column__item-description {
order: 2;
}

cogniSyb marked this conversation as resolved.
Show resolved Hide resolved
@media (min-width: 1024px) {
.section.v2-accordion-column-container {
height: 780px;
}

.section > .v2-accordion-column-wrapper.full-width {
max-width: 1440px;
margin: 0 auto;
position: relative;
}

.v2-accordion-column__header-container {
max-width: var(--wrapper-width);
margin: 0 auto 4em;
}

.v2-accordion-column__header-container h2 {
font-size: var(--headline-1-font-size);
}

.v2-accordion-column__accordion-container {
cogniSyb marked this conversation as resolved.
Show resolved Hide resolved
display: flex;
justify-content: end;
max-width: var(--wrapper-width);
margin: 0 auto;
}

.v2-accordion-column__items-container {
display: flex;
flex-direction: column;
align-items: flex-start;
margin: 0;
}

.v2-accordion-column__item {
max-width: 343px;
width: 100%;
}

.v2-accordion-column__item,
.v2-accordion-column__item.active {
margin: 0 0 20px;
}

.v2-accordion-column__item-image {
position: absolute;
left: 0;
top: 6em;
width: calc(50% + 80px);
background-color: var(--c-primary-gray);
}

.v2-accordion-column__item-description > p:not(.button-container) {
padding: 0;
}

/* Left variant */
.v2-accordion-column--left .v2-accordion-column__accordion-container {
justify-content: start;
}

.v2-accordion-column--left .v2-accordion-column__items-container {
width: 40%;
}

.v2-accordion-column--left .v2-accordion-column__item-image {
left: calc(50% - 80px);
}
}
68 changes: 68 additions & 0 deletions blocks/v2-accordion-column/v2-accordion-column.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { createElement, variantsClassesToBEM } from '../../scripts/common.js';

const CLASSES = {
blockName: 'v2-accordion-column',
left: 'left',
};

const { blockName, left } = CLASSES;
const variants = Object.values(CLASSES).splice(1);

const addAccordionClass = (item) => {
const hasPicture = item.querySelector('picture');
if (hasPicture) item.classList.add(`${blockName}__item-image`);
else {
const header = item.querySelector(':is(h1, h2, h3, h4, h5, h6)');
if (header) header.classList.add(`${blockName}__item-title`);
item.classList.add(`${blockName}__item-description`);
}
};

export default function decorate(block) {
const header = block.querySelector(':scope > div:first-child > div > :first-child');
const accordionItems = [...block.querySelectorAll(':scope > div:not(:first-child)')];
const accordionContainer = createElement('div', { classes: `${blockName}__accordion-container` });
const itemsContainer = createElement('div', { classes: `${blockName}__items-container` });
const hasLeftClass = block.classList.contains(left); // accordion at left side
/** @type {boolean} */
const isLeftVariant = hasLeftClass
|| (!hasLeftClass && !!accordionItems[0].lastElementChild.querySelector('picture'));
if (!hasLeftClass && isLeftVariant) block.classList.add(left);
variantsClassesToBEM(block.classList, variants, blockName);
block.parentElement.classList.add('full-width');
header.parentElement.classList.add(`${blockName}__header-wrapper`);
header.parentElement.parentElement.classList.add(`${blockName}__header-container`);

// style the header as an h2 with red marker over it
header.classList.add(`${blockName}__header`, 'with-marker');

// is responsibility of the author to add the proper amount of images and text
accordionItems.forEach((item, i) => {
const colBtnTitle = createElement('button', {
classes: `${blockName}__item-header-button`,
props: { type: 'button' },
});
const arrowEl = createElement('div', { classes: [`${blockName}__close`, 'icon'] });
const dropdownArrowIcon = document.createRange().createContextualFragment(`
<svg xmlns="http://www.w3.org/2000/svg"><use href="#icons-sprite-dropdown-caret"></use></svg>`);
const colItems = [...item.querySelectorAll(':scope > div')];

// add the proper classes to each accordion item
item.classList.add(`${blockName}__item`);
if (i === 0) item.classList.add('active');
colItems.forEach((col) => addAccordionClass(col));
arrowEl.appendChild(...dropdownArrowIcon.children);
colBtnTitle.prepend(item.querySelector(`.${blockName}__item-title`), arrowEl);
colBtnTitle.onclick = () => {
const active = accordionContainer.querySelector('.active');
if (active && active !== item) active.classList.remove('active');
item.classList.add('active');
};
item.prepend(colBtnTitle);
itemsContainer.appendChild(item);
});

accordionContainer.append(itemsContainer);

block.appendChild(accordionContainer);
}
Loading