generated from adobe/aem-boilerplate
-
Notifications
You must be signed in to change notification settings - Fork 3
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 #117 from hlxsites/timeline-slider
Added timeline slider
- Loading branch information
Showing
2 changed files
with
304 additions
and
0 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,175 @@ | ||
/* Container styles */ | ||
.timeline-slide { | ||
display: flex; | ||
flex-direction: column; | ||
align-items: center; | ||
padding: 40px 0; | ||
overflow: hidden; | ||
} | ||
|
||
/* Slider styles */ | ||
#year-slider { | ||
display: flex; | ||
overflow: hidden; | ||
transform: translate3d(43%, 0, 0); | ||
transition: 0.5s all ease-in-out; | ||
transition-duration: 0ms; | ||
} | ||
|
||
.year { | ||
cursor: pointer; | ||
border-radius: 5px; | ||
color: #dbdbdb; | ||
font-size: 40px; | ||
font-weight: 700; | ||
transition: 0.3s all ease-in-out; | ||
text-align: center; | ||
} | ||
|
||
.year:hover, .year.active { | ||
color: #f49600; | ||
transition: 0.3s all ease-in-out; | ||
} | ||
|
||
/* Content area styles */ | ||
#content-slider-container { | ||
position: relative; | ||
width: 100%; | ||
} | ||
|
||
#content-slider { | ||
/* width: 100%; */ | ||
display: flex; | ||
align-items: center; | ||
min-height: 250px; | ||
max-width: 600px; | ||
margin: 0 auto; | ||
overflow: hidden; | ||
} | ||
|
||
#content-slider li::before { | ||
color: var(--primary-color); | ||
content: "\25A0"; | ||
font-family: Arial; | ||
font-size: 1em; | ||
left: 0; | ||
line-height: 100%; | ||
position: absolute; | ||
top: 0.45em; | ||
} | ||
|
||
.year-content { | ||
display: none; | ||
transition: transform 0.5s ease, opacity 0.5s ease; | ||
opacity: 0; | ||
left: 0; | ||
right: 0; | ||
} | ||
|
||
.year-content.active { | ||
display: block; | ||
opacity: 1; | ||
transform: translateX(0); | ||
} | ||
|
||
/* buttons */ | ||
.button-container { | ||
width: 100%; | ||
position: absolute; | ||
height: 100%; | ||
top: 0; | ||
left: 0; | ||
right: 0; | ||
bottom: 0; | ||
display: flex; | ||
align-items: center; | ||
justify-content: space-between; | ||
} | ||
|
||
.button-container .hide { | ||
opacity: 0.5; | ||
} | ||
|
||
.button-prev { | ||
border: 2px solid #f49600; | ||
border-radius: 50%; | ||
color: #f49600; | ||
cursor: pointer; | ||
height: 50px; | ||
text-align: center; | ||
transition: all .3s; | ||
user-select: none; | ||
width: 50px; | ||
position: relative; | ||
float: left; | ||
margin: 15px; | ||
} | ||
|
||
.button-prev::after { | ||
content: ''; | ||
border: 2px solid #f49600; | ||
border-width: 0 2px 2px 0; | ||
transform: rotate(135deg); /* Rotates the arrow to point left */ | ||
position: absolute; | ||
top: 15px; | ||
left: 20px; | ||
right: 0; | ||
bottom: 0; | ||
width: 20px; | ||
height: 20px; | ||
} | ||
|
||
.button-next { | ||
border: 2px solid #f49600; | ||
border-radius: 50%; | ||
color: #f49600; | ||
cursor: pointer; | ||
height: 50px; | ||
text-align: center; | ||
transition: all .3s; | ||
user-select: none; | ||
width: 50px; | ||
position: relative; | ||
float: right; | ||
margin: 15px; | ||
} | ||
|
||
|
||
|
||
.button-next:hover { | ||
background-color: #f49600; | ||
} | ||
|
||
.button-next:hover::after { | ||
border-color: #fff; | ||
} | ||
|
||
|
||
.button-prev:hover { | ||
background-color: #f49600; | ||
} | ||
|
||
.button-prev:hover::after { | ||
border-color: #fff; | ||
} | ||
|
||
.button-next::after { | ||
content: ''; | ||
border: 2px solid #f49600; | ||
border-width: 0 2px 2px 0; | ||
transform: rotate(315deg); /* Rotates the arrow to point left */ | ||
position: absolute; | ||
top: 15px; | ||
left: 10px; | ||
right: 0; | ||
bottom: 0; | ||
width: 20px; | ||
height: 20px; | ||
} | ||
|
||
@media (max-width: 767px) { | ||
.button-container { | ||
position: relative; | ||
justify-content: center; | ||
} | ||
} |
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,129 @@ | ||
import { div } from '../../scripts/dom-builder.js'; | ||
|
||
export default function decorate(block) { | ||
const yearSlider = div({ id: 'year-slider' }); | ||
const contentSliderContainer = div({ id: 'content-slider-container' }); | ||
const contentSlider = div({ id: 'content-slider' }); | ||
const nextButton = div({ class: 'button-block' }, div({ class: 'button-next' })); | ||
const prevButton = div({ class: 'button-block' }, div({ class: 'button-prev' })); | ||
const buttonContainer = div({ class: 'button-container' }); | ||
let activeYearIndex = 0; | ||
|
||
buttonContainer.appendChild(prevButton); | ||
buttonContainer.appendChild(nextButton); | ||
|
||
function translateYearSlider() { | ||
const yearWidth = yearSlider.children[0].offsetWidth; | ||
const translateDistance = yearWidth * activeYearIndex; | ||
yearSlider.style.transform = `translate3d(calc( 43% - ${translateDistance}px ), 0px, 0px)`; | ||
} | ||
|
||
// Function to clear all active classes | ||
function clearActiveClasses() { | ||
[...yearSlider.children].forEach((year) => { | ||
year.classList.remove('active'); | ||
}); | ||
[...contentSlider.children].forEach((content) => { | ||
content.classList.remove('active'); | ||
}); | ||
} | ||
|
||
function applySlideEffect(index, direction) { | ||
const content = block.querySelector(`#content-${yearSlider.children[index].textContent.trim()}`); | ||
if (content) { | ||
// Apply sliding effect | ||
content.style.transform = `translateX(${direction === 'left' ? '100%' : '-100%'})`; | ||
setTimeout(() => { | ||
content.style.transform = 'translateX(0)'; | ||
}, 50); // Delay to ensure the transition effect is applied | ||
} | ||
} | ||
|
||
nextButton.addEventListener('click', () => { | ||
// Calculate the next index | ||
const nextIndex = activeYearIndex + 1; | ||
|
||
if (nextIndex < yearSlider.children.length) { | ||
// Move to the next year and update the active index | ||
yearSlider.children[nextIndex].click(); | ||
activeYearIndex = nextIndex; | ||
// Always show the prev button when moving forward | ||
prevButton.classList.remove('hide'); | ||
translateYearSlider(); | ||
} | ||
|
||
// Hide the next button if we reach the end | ||
if (nextIndex === yearSlider.children.length - 1) { | ||
nextButton.classList.add('hide'); | ||
} | ||
}); | ||
|
||
prevButton.addEventListener('click', () => { | ||
const prevIndex = activeYearIndex - 1; | ||
|
||
if (prevIndex >= 0) { | ||
// Move to the previous year and update the active index | ||
yearSlider.children[prevIndex].click(); | ||
activeYearIndex = prevIndex; | ||
|
||
// Always show the next button when moving backward | ||
nextButton.classList.remove('hide'); | ||
|
||
// Translate the year slider | ||
translateYearSlider(); | ||
} | ||
|
||
// Hide the prev button if we reach the beginning | ||
if (prevIndex === 0) { | ||
prevButton.classList.add('hide'); | ||
} | ||
}); | ||
|
||
[...block.children].forEach((child) => { | ||
if (child.children.length >= 2) { | ||
const yearChild = child.children[0].cloneNode(true); | ||
yearChild.classList.add('year'); | ||
yearChild.style.width = '130px'; | ||
yearSlider.appendChild(yearChild); | ||
const contentChild = child.children[1].cloneNode(true); | ||
contentChild.classList.add('year-content'); | ||
contentChild.id = `content-${yearChild.innerText}`; | ||
contentSlider.appendChild(contentChild); | ||
} | ||
}); | ||
|
||
block.innerHTML = ''; | ||
block.appendChild(yearSlider); | ||
contentSliderContainer.appendChild(contentSlider); | ||
contentSliderContainer.appendChild(buttonContainer); | ||
block.appendChild(contentSliderContainer); | ||
block.classList.add('clearfix'); | ||
|
||
[...yearSlider.children].forEach((year, index) => { | ||
year.addEventListener('click', () => { | ||
clearActiveClasses(); | ||
|
||
// Check direction for slide effect | ||
const direction = index > activeYearIndex ? 'left' : 'right'; | ||
applySlideEffect(index, direction); | ||
|
||
// Update active year | ||
activeYearIndex = index; | ||
|
||
translateYearSlider(); | ||
|
||
year.classList.add('active'); | ||
const contentId = `#content-${year.textContent.trim()}`; | ||
block.querySelector(contentId).classList.add('active'); | ||
}); | ||
}); | ||
|
||
function makeElementActive() { | ||
yearSlider.children[0].classList.add('active'); | ||
contentSlider.children[0].classList.add('active'); | ||
activeYearIndex = 0; | ||
prevButton.classList.add('hide'); | ||
} | ||
|
||
makeElementActive(); | ||
} |