JSFiddle - React, Tailwind, and code Playground
by mariomc
HTML
<body>
<div class="outer-container">
<div class="container">
</div>
</div>
<p>
<button class="prev-button">Prev</button>
<button class="next-button">Next</button>
</p>
</body>
CSS
.outer-container {
width: 100vw;
margin: 0 auto;
}
.container {
/* Container is not 100% just for debug/visualization purposes */
width: 50%;
margin: 0 auto;
height: 200px;
position: relative;
}
.slide {
height: 100%;
font-size: 5rem;
position: absolute;
inset: 0;
background-color: white;
outline: 1px solid red;
align-items: center;
justify-content: center;
display: flex;
}
.animating {
background: green;
}
.active {
z-index: 1;
transform: translate3d(0, 0, 0);
}
.prev {
z-index: 2;
transform: translate3d(-100%, 0, 0);
}
.next {
z-index: 2;
transform: translate3d(100%, 0, 0);
}
JavaScript
const NEXT = 'next';
const PREV = 'prev';
const ACTIVE = 'active';
const ANIMATION_DURATION = 5000;
const container = document.querySelector('.container');
const removeAllStateClasses = ({
active,
next
}) => {
active.classList.remove(ACTIVE);
next.classList.remove(NEXT, PREV);
}
const addAllStateClasses = ({
active,
}) => {
active.classList.add(ACTIVE);
}
const buildSlides = (number) => {
const slides = Array(number).fill(0);
const slidesHTML = slides.map((slide, index) => `<div class="slide">${index +1}</div>`).join("");
container.innerHTML = slidesHTML;
const all = Array.from(container.querySelectorAll('.slide'));
const [active] = all;
addAllStateClasses(active);
return { active, first: all.at(0), last: all.at(-1) };
}
const { first, last, all, ...rest } = buildSlides(4);
let state = {
active,
direction: NEXT,
animation: null,
};
addAllStateClasses({
active
});
const setState = (newState) => {
state = {
...state,
...newState
};
}
const animationStart = (oldState, newState, animation) => {
const direction = newState.direction;
setState({
animation
});
oldState.next.classList.remove('prev', 'next');
newState.next.classList.add(direction);
newState.active.classList.add('animating');
}
const animationEnd = (oldState, newState) => {
newState.active.classList.remove('animating');
removeAllStateClasses(oldState);
addAllStateClasses(newState);
setState({
...newState,
animation: null
});
};
const selectActive = (state, direction) => {
if (direction === NEXT) return state.active.nextElementSibling || first;
return state.active.previousElementSibling || last;
}
const move = (previousState, direction = NEXT) => {
// Represents the next slide in the current direction
const active = selectActive(previousState, direction);
const newState = {
active,
next,
direction,
};
return newState;
}
const transitionState = async (oldState, newState) => {
const...