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

VAT: adding logo block and carousel block #3

Merged
merged 4 commits into from
Jun 10, 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
227 changes: 227 additions & 0 deletions blocks/carousel/carousel.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,227 @@
.section.carousel-container {
padding: 0;
}

.carousel .carousel-slides-container {
position: relative;
}

.carousel .carousel-slides,
.carousel .carousel-slide-indicators {
list-style: none;
margin: 0;
padding: 0;
}

.carousel .carousel-slides {
display: flex;
scroll-behavior: smooth;
scroll-snap-type: x mandatory;
overflow: scroll clip;
}

.carousel .carousel-slides::-webkit-scrollbar {
display: none;
}

.carousel .carousel-slide {
flex: 0 0 100%;
scroll-snap-align: start;
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: center;
position: relative;
width: 100%;
min-height: 1015px;
}

.carousel .carousel-slide:has(.carousel-slide-content[data-align="center"]) {
align-items: center;
}

.carousel .carousel-slide:has(.carousel-slide-content[data-align="right"]) {
align-items: flex-end;
}

.carousel .carousel-slide .carousel-slide-image picture {
position: absolute;
inset: 0;
}

.carousel .carousel-slide .carousel-slide-image picture > img {
height: 100%;
width: 100%;
object-fit: cover;
}

.carousel .carousel-slide .carousel-slide-content {
z-index: 1;
padding: 1rem;
margin: 1.5rem 3rem;
color: white;
background-color: none;
position: relative;
width: var(--slide-content-width, auto);
}

.carousel .carousel-slide .carousel-slide-content .button {
display: flex;
max-width: 260px;
align-items: center;
max-height: 60px;
position: relative;
border: 0;
height: 6rem;
width: 100%;
font-family: Calibre, Helvetica, Tahoma, Arial, sans-serif;
cursor: pointer;
appearance: none;
border-radius: .4rem;
transition: all .2s ease-in-out;
background: #80ba27;
color: #fff;
letter-spacing: -.02rem;
box-shadow: 0 .2rem .4rem 0 rgba(0 0 0 / 5%);
font-size: 18px;
font-weight: normal;
}

.carousel .carousel-slide-image::after {
width: 100vw;
height: 100vh;
display: block;
position: absolute;
top:0;
left: 0;
background-color: rgba(0 0 0 /30%);
content: " ";
}

.carousel .carousel-slide-indicators {
display: flex;
justify-content: center;
gap: 0.5rem;
}

.carousel .carousel-slide-indicator button {
width: 1rem;
height: 1rem;
padding: 0;
border-radius: 1rem;
background-color: rgba(0 0 0 / 25%);
}

.carousel .carousel-slide-indicator button:disabled,
.carousel .carousel-slide-indicator button:hover,
.carousel .carousel-slide-indicator button:focus-visible {
background-color: rgba(0 0 0 / 80%);
}

.carousel .carousel-slide-indicator span,
.carousel .carousel-navigation-buttons span {
border: 0;
clip: rect(0 0 0 0);
clip-path: inset(50%);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
white-space: nowrap;
}

.carousel .carousel-navigation-buttons {
position: absolute;
top: 50%;
transform: translateY(-50%);
left: 0.5rem;
right: 0.5rem;
display: flex;
align-items: center;
justify-content: flex-end;
gap: 20px;
margin-right: 5rem;
z-index: 1;
}

/* stylelint-disable-next-line no-descending-specificity */
.carousel .carousel-navigation-buttons button {
border-radius: 8px;
margin: 0;
padding: 0;
width: 2rem;
height: 2rem;
position: relative;
background-color: transparent;
}

.carousel .carousel-navigation-buttons button:hover,
.carousel .carousel-navigation-buttons button:focus-visible {
background-color: transparent;
}

.carousel .carousel-navigation-buttons button::after {
display: block;
content: "";
border: 3px white solid;
border-bottom: 0;
border-left: 0;
height: 0.75rem;
width: 0.75rem;
position: absolute;
top: 50%;
left: calc(50% + 3px);
transform: translate(-50%, -50%) rotate(-135deg);
}

.carousel .carousel-navigation-buttons button.slide-next::after {
transform: translate(-50%, -50%) rotate(45deg);
left: calc(50% - 3px);
}

@media (width >= 600px) {
.carousel .carousel-navigation-buttons {
left: 1rem;
right: 1rem;
}

.carousel .carousel-navigation-buttons button {
width: 3rem;
height: 3rem;
}

.carousel .carousel-navigation-buttons button::after {
width: 1rem;
height: 1rem;
}

.carousel .carousel-slide .carousel-slide-content {
--slide-content-width: 50%;

margin: 2.5rem 5rem;
}

.carousel .carousel-slide .carousel-slide-content h3 {
color: #fff;
}

.carousel .carousel-slide .carousel-slide-content[data-align="justify"] {
--slide-content-width: auto;
}
}


.carousel-container .carousel-wrapper {
max-width: 100%;
height: calc(100vh - 64px);
min-height: calc(100vh - 64px);
}

@media (width >= 900px) {
.carousel-container .carousel-wrapper {
max-width: 100%;
min-height: 1015px;
}
}
150 changes: 150 additions & 0 deletions blocks/carousel/carousel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
import { fetchPlaceholders } from '../../scripts/aem.js';

function updateActiveSlide(slide) {
const block = slide.closest('.carousel');
const slideIndex = parseInt(slide.dataset.slideIndex, 10);
block.dataset.activeSlide = slideIndex;

const slides = block.querySelectorAll('.carousel-slide');

slides.forEach((aSlide, idx) => {
aSlide.setAttribute('aria-hidden', idx !== slideIndex);
aSlide.querySelectorAll('a').forEach((link) => {
if (idx !== slideIndex) {
link.setAttribute('tabindex', '-1');
} else {
link.removeAttribute('tabindex');
}
});
});

const indicators = block.querySelectorAll('.carousel-slide-indicator');
indicators.forEach((indicator, idx) => {
if (idx !== slideIndex) {
indicator.querySelector('button').removeAttribute('disabled');
} else {
indicator.querySelector('button').setAttribute('disabled', 'true');
}
});
}

function showSlide(block, slideIndex = 0) {
const slides = block.querySelectorAll('.carousel-slide');
let realSlideIndex = slideIndex < 0 ? slides.length - 1 : slideIndex;
if (slideIndex >= slides.length) realSlideIndex = 0;
const activeSlide = slides[realSlideIndex];

activeSlide.querySelectorAll('a').forEach((link) => link.removeAttribute('tabindex'));
block.querySelector('.carousel-slides').scrollTo({
top: 0,
left: activeSlide.offsetLeft,
behavior: 'smooth',
});
}

function bindEvents(block) {
const slideIndicators = block.querySelector('.carousel-slide-indicators');
if (!slideIndicators) return;

slideIndicators.querySelectorAll('button').forEach((button) => {
button.addEventListener('click', (e) => {
const slideIndicator = e.currentTarget.parentElement;
showSlide(block, parseInt(slideIndicator.dataset.targetSlide, 10));
});
});

block.querySelector('.slide-prev').addEventListener('click', () => {
showSlide(block, parseInt(block.dataset.activeSlide, 10) - 1);
});
block.querySelector('.slide-next').addEventListener('click', () => {
showSlide(block, parseInt(block.dataset.activeSlide, 10) + 1);
});

const slideObserver = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) updateActiveSlide(entry.target);
});
}, { threshold: 0.5 });
block.querySelectorAll('.carousel-slide').forEach((slide) => {
slideObserver.observe(slide);
});
}

function createSlide(row, slideIndex, carouselId) {
const slide = document.createElement('li');
slide.dataset.slideIndex = slideIndex;
slide.setAttribute('id', `carousel-${carouselId}-slide-${slideIndex}`);
slide.classList.add('carousel-slide');

row.querySelectorAll(':scope > div').forEach((column, colIdx) => {
column.classList.add(`carousel-slide-${colIdx === 0 ? 'image' : 'content'}`);
slide.append(column);
});

const labeledBy = slide.querySelector('h1, h2, h3, h4, h5, h6');
if (labeledBy) {
slide.setAttribute('aria-labelledby', labeledBy.getAttribute('id'));
}

return slide;
}

let carouselId = 0;
export default async function decorate(block) {
carouselId += 1;
block.setAttribute('id', `carousel-${carouselId}`);
const rows = block.querySelectorAll(':scope > div');
const isSingleSlide = rows.length < 2;

const placeholders = await fetchPlaceholders();

block.setAttribute('role', 'region');
block.setAttribute('aria-roledescription', placeholders.carousel || 'Carousel');

const container = document.createElement('div');
container.classList.add('carousel-slides-container');

const slidesWrapper = document.createElement('ul');
slidesWrapper.classList.add('carousel-slides');
block.prepend(slidesWrapper);

let slideIndicators;
if (!isSingleSlide) {
const slideIndicatorsNav = document.createElement('nav');
slideIndicatorsNav.setAttribute('aria-label', placeholders.carouselSlideControls || 'Carousel Slide Controls');
slideIndicators = document.createElement('ol');
slideIndicators.classList.add('carousel-slide-indicators');
slideIndicatorsNav.append(slideIndicators);
block.append(slideIndicatorsNav);

const slideNavButtons = document.createElement('div');
slideNavButtons.classList.add('carousel-navigation-buttons');
slideNavButtons.innerHTML = `
<button type="button" class= "slide-prev" aria-label="${placeholders.previousSlide || 'Previous Slide'}"></button>
<button type="button" class="slide-next" aria-label="${placeholders.nextSlide || 'Next Slide'}"></button>
`;

container.append(slideNavButtons);
}

rows.forEach((row, idx) => {
const slide = createSlide(row, idx, carouselId);
slidesWrapper.append(slide);

if (slideIndicators) {
const indicator = document.createElement('li');
indicator.classList.add('carousel-slide-indicator');
indicator.dataset.targetSlide = idx;
indicator.innerHTML = `<button type="button"><span>${placeholders.showSlide || 'Show Slide'} ${idx + 1} ${placeholders.of || 'of'} ${rows.length}</span></button>`;
slideIndicators.append(indicator);
}
row.remove();
});

container.append(slidesWrapper);
block.prepend(container);

if (!isSingleSlide) {
bindEvents(block);
}
}
3 changes: 3 additions & 0 deletions blocks/logo/logo.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.logo {
display: block;
}
Binary file modified favicon.ico
Binary file not shown.
13 changes: 13 additions & 0 deletions icons/arrow-right.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading