Skip to content

Commit

Permalink
Accordion column block #114 (#203)
Browse files Browse the repository at this point in the history
  • Loading branch information
jonatan-lledo-netcentric authored Feb 15, 2024
1 parent 636c424 commit 7fad9e9
Show file tree
Hide file tree
Showing 2 changed files with 273 additions and 0 deletions.
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%;
}

.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 {
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 {
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;
}

.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;
display: block;
}

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

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

@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 {
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);
}

0 comments on commit 7fad9e9

Please sign in to comment.