JSFiddle - React, Tailwind, and code Playground

by mariomc

HTML

<body>
  <div class="outer-container">
    <div class="container">
      <div class="slide prev">1</div>
      <div class="slide active">2</div>
      <div class="slide next">3</div>
      <div class="slide">4</div>
      <div class="slide">5</div>
      <div class="slide">6</div>
      <div class="slide">7</div>
      <div class="slide">8</div>
      <div class="slide">9</div>

    </div>

  </div>


  <p>
    <button class="prev-button">Prev</button>
    <button class="next-button">Next</button>
  </p>
</body>

CSS

.outer-container {
  width: 400px;
  margin: 0 auto;
}

.container {
  width: 50%;
  margin: 0 auto;
  height: 200px;
  position: relative;
}

.slide {
  height: 100%;
  font-size: 5rem;
  position: absolute;
  inset: 0;
  background-color: white;
  border: 1px solid red;
  align-items: center;
  justify-content: center;
  display: flex;
}

.animating {
  background: green;
}

.active {
  z-index: 1;
  opacity: 1;
  transform: translate3d(0, 0, 0);
}

.prev {
  z-index: 2;
  opacity: 1;
  transform: translate3d(-100%, 0, 0);
}

.next {
  z-index: 2;
  opacity: 1;
  transform: translate3d(100%, 0, 0);
}

JavaScript

const prevButton = document.querySelector('.prev-button');
const nextButton = document.querySelector('.next-button');
const first = document.querySelector('.slide:first-child');
const last = document.querySelector('.slide:last-child');

let state = {
  active: document.querySelector('.active'),
  prev: document.querySelector('.prev'),
  next: document.querySelector('.next'),
  animation: null,
};

const setState = (newState) => {
  state = {
    ...state,
    ...newState
  };
}

const toActiveAnimation = [{
  transform: "translate3d(0,0,0)"
}];

const ANIMATION_DURATION = 5000;

const removeAllStateClasses = ({
  active,
  prev,
  next
}) => {
  active.classList.remove('active');
  prev.classList.remove('prev');
  next.classList.remove('next');
}

const addAllStateClasses = ({
  active,
  prev,
  next
}) => {
  active.classList.add('active');
  prev.classList.add('prev');
  next.classList.add('next');
}

const animationStart = (oldState, newState, animation) => {
  setState({
    animation
  });
  newState.active.classList.add('animating');
}

const animationEnd = (oldState, newState) => {
  newState.active.classList.remove('animating');
  removeAllStateClasses(oldState);
  addAllStateClasses(newState);

  setState({
    ...newState,
    animation: null
  });
};

const NEXT = 'next';
const PREV = 'prev';

const selectNextUp = (state, slide, direction) => {
  if (direction === NEXT) return slide.nextElementSibling || first;
  return slide.previousElementSibling || last;
}

const move = (state, direction = NEXT) => {
  // The "next"/"prev" will become the new active
  const active = state[direction];
  // Represents the next slide in the current direction
  const nextUp = selectNextUp(state, active, direction);
  const oppositeDirection = direction === NEXT ? PREV : NEXT;
  return {
    active,
    [oppositeDirection]: state.active,
    [direction]: nextUp
  }
}

const transitionState = async (oldState, newState) => {
  const animation =...