generated from adobe/aem-boilerplate
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3 from Netcentric/VAT-hero-carousel
VAT: adding logo block and carousel block
- Loading branch information
Showing
6 changed files
with
395 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.logo { | ||
display: block; | ||
} |
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.