JSFiddle - React, Tailwind, and code Playground

by joplomacedo

HTML

<button data-state="loading" class="btn">

  <span class="btn__content">
    <span class="if if-idle">Submeter</span>
    <span class="if if-loading">Submetendo. Aguarde por favor.</span>
    <span class="if if-success">Submetido. Obrigado.</span>
  </span>
  
  <span class="btn__loadingBar">
    <span class="btn__loadingBar__grower"></span>
  </span>
</button>

CSS

*,
*:before,
*:after{
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  border: 0;
  background: none;
  font: inherit;
  outline: none;
}

html {
  font-family: -apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Fira Sans","Droid Sans","Helvetica Neue",Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";
}


.btn {
  position: relative;
  cursor: pointer;
  padding: 1em;
  background-color: red;
  color: #fff;
  border-radius: 3px;
}

.btn .btn__content > .if {
  display: none;
}

.btn[data-state="idle"] .btn__content > .if-idle,
.btn[data-state="loading"] .btn__content > .if-loading,
.btn[data-state="success"] .btn__content > .if-success {
  display: block;
}


.btn__loadingBar {
  height: 5px;
  position: absolute;
  bottom: 0;
  left: 0;
  right: 0;
  background-color: rgba(255,255,255,.3);
}

.btn__loadingBar__grower {
  display: block;
  width: 0;
  height: 100%;
  background-color: rgba(255,255,255,.7);
}

/* state */
.btn[data-state="loading"] .btn--loadingBar {
  display: block;
}

.btn[data-state="loading"] .btn__loadingBar__grower,
.btn[data-state="success"] .btn__loadingBar__grower {
  animation-name: grow;
	animation-fill-mode: both;
}

.btn[data-state="loading"] .btn__loadingBar__grower {
  animation-duration: 30s;
}

.btn[data-state="success"] .btn__loadingBar__grower {
  animation-duration: 3.6s;
}

@keyframes grow{
  0%{
    width: 0%;
  }
  100%{
    width: 100%;
  }
}

JavaScript

const btn = document.querySelector('.btn')

let completeTimeout;

btn.addEventListener('click', () => {
  clearTimeout(completeTimeout);
  startLoading(btn);

  completeTimeout = setTimeout(() => {
    completeLoading(btn)
  }, 3000);
})


function startLoading(btn) {
  btn.setAttribute('data-state', 'loading');
}

function completeLoading(btn) {
  btn.setAttribute('data-state', 'success');
}