<button id="js-btn" class="btn btn-green btn-lg">
  <span class="text">Submit</span>
  <div class="timer">
    <svg id="js-timer" viewBox="0 0 120 120" xmlns='http://www.w3.org/2000/svg'><circle cx="60" cy="60" r="55"/></svg>
  </div>
  <div class="icon-success"><svg viewBox="0 0 50 45" xmlns='http://www.w3.org/2000/svg'><path d="M20,42 L3, 25"/><path d="M20,42 L47,3"/></svg></div>
</button>

<button id="js-reset" class="btn btn-sm btn-black top-left">Reset</button>

<!-- https://uimovement.com/ui/2380/submit-button/ -->
$green: #2BCB96
$gray: #BBBBBB

$btn_w: 380px
$btn_h: 120px

$timer_w: $btn_h

$success_w: 50px
$success_h: 45px

/* -------------------------------- resets */
body, button, div, span, svg
  margin: 0
  padding: 0
  box-sizing: border-box

/* --------------------------- base styles */
body
  display: flex
  align-items: center
  justify-content: center
  width: 100vw
  height: 100vh
  
svg
  width: 100%
  height: 100%
  
/* ------------------------------- buttons */  
.btn
  position: relative
  display: flex
  align-items: center
  justify-content: center
  margin-bottom: 50px
  font-family: 'Work Sans', sans-serif
  transition: all .5s ease-in-out
  outline: none
  
.btn-lg
  width: $btn_w
  height: $btn_h
  border: 5px solid
  border-radius: $btn_h/2
  font-size: 30px
  font-weight: 600
  letter-spacing: 1.5px
  
.btn-sm
  width: 100px
  height: 40px
  border: none
  border-radius: 3px
  font-size: 16px

.btn-green
  color: $green
  background: white
  border-color: $green
  &:hover
    color: white
    background: $green
  
.btn-black
  color: white
  background: darkgray
  &:hover
    background: black
  
/* --------------------------------- timer */  
.timer
  position: absolute
  left: calc(50% - #{$timer_w}/2)
  width: $timer_w
  height: $timer_w
  opacity: 0
  svg
    fill: none
    stroke: $green
    stroke-width: 10px   
    transform: rotate(-.25turn)
    transform-origin: center center
    stroke-dasharray: 383
    stroke-dashoffset: 383
    transition: stroke-dashoffset .3s ease-in-out 
    
/* -------------------------- icon success */  
.icon-success
  position: absolute
  top: 35px
  left: calc(50% - #{$success_w}/2)
  width: $success_w
  height: $success_h
  border: black
  svg
    fill: none
    stroke: white
    stroke-width: 6px
    stroke-linecap: round
    stroke-dasharray: 50
    stroke-dashoffset: 50
    transition: stroke-dashoffset .2s .2s linear
    opacity: 0
 
/* ------------------------- button states */
/* ----------------------- do submit */  
.do-submit
  color: white
  background: $green
  border-color: $green
  animation: closeButton .3s .3s ease-in forwards
  .text
    animation: hideText .3s forwards
  .timer
    transition: opacity .1s .6s linear
    opacity: 1
    z-index: 1
  
/* -------------------------- succes */  
.success
  border-color: $green
  animation: openButton .3s ease-in forwards
  .timer
    opacity: 0
    transition: opacity .01s linear
  .icon-success svg
    opacity: 1
    stroke-dashoffset: 0

/* --------------------------- reset */    
.reset 
  animation: resetButton .5s ease-in forwards
  .icon-success
    opacity: 0
  .text
    animation: showText .8s ease-in forwards
 
/* ----------------------------- keyframes */
@keyframes closeButton
  90%
    width: $timer_w
    height: $timer_w
    background: white
    border-width: 10px
    border-color: $gray
  100%
    width: $timer_w
    height: $timer_w
    background: white
    border-width: 10px
    border-color: $gray
    border-radius: 50%
  
@keyframes openButton
  from
    width: $timer_w
    height: $timer_w
    background: white
    border-color: $green
    border-width: 10px
    border-radius: 50%
  90%
    width: $btn_w
    height: $btn_h
    background: $green
    border-width: 5px
  100%
    width: $btn_w
    height: $btn_h
    background: $green
    border-color: $green
    border-width: 5px
    border-radius: $btn_h/2
  
@keyframes resetButton
  to
    background: white
    color: $green

@keyframes hideText
  from
    opacity: 1
    transform: scaleX(1)
  20%
    transform: scaleX(1.1)
  40%
    opacity: 1
    transform: scaleX(1)
  to
    opacity: 0
    
@keyframes showText
  from
    opacity: 0
  to
    opacity: 1
    
/* ----------------------- utility classes */
.top-left
  position: absolute
  top: 30px
  left: 20px
View Compiled
var button = document.getElementById('js-btn'),
    timer = document.getElementById('js-timer'),
    reset = document.getElementById('js-reset');


button.addEventListener('click', doSubmit);
reset.addEventListener('click', resetButton);


function doSubmit() {
  
  if (button.classList.contains('do-submit')) { return; }

  // do clicked animation
  button.classList.add('do-submit');
  
  // TODO handle submit, should return amountLoaded
  
  // manually feed amountLoaded as if receiving 0-100% values
  setTimeout(function() {
    doTimer(0);
  }, 1200);
  
  setTimeout(function() {
    doTimer(15);
  }, 1200);

  setTimeout(function() {
    doTimer(75); 
  }, 2000);

  setTimeout(function() {
    doTimer(100);
  }, 2800);
}


function doTimer(amountLoaded) { 
  
  timer.style.strokeDashoffset = 3.83 * (100 - amountLoaded) + 'px';

  if (amountLoaded === 100) {
    setTimeout(function() {
      button.classList.add('success');
    }, 500);
  }
}


function resetButton() {
  // reset button classes
  button.classList.add('reset');
  setTimeout(function() {
    button.classList.remove('success');
    button.classList.remove('do-submit');
    button.classList.remove('reset');
  }, 500);
  // reset timer animation
  timer.style.strokeDashoffset = '383px';
  // reset timer counter
  time = 110;
}


External CSS

This Pen doesn't use any external CSS resources.

External JavaScript

This Pen doesn't use any external JavaScript resources.