Sample loading Buttons

by philll_t

HTML

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.11/vue.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.1.0/animate.min.css">

<div id='main' 
     class="container text-center">
  <template v-for="(class_name, index) in loadingClasses">
    <div :key='class_name'>
      <br />
      
      <strong>
       {{class_name}}     
      </strong>
   
      <br />
      
      <button :class="`btn btn-primary ${class_name} ${modifier}`" 
              v-on:click="loading = !loading" 
               >
        <transition name="`transition-${index}`" mode="out-in"
                    :enter-active-class="`animate__animated animate__${enterAnimationClasses[index]}`"
                    :leave-active-class="`animate__animated animate__${leaveAnimationClasses[index]}`"> 
          <span v-if="modifier === 'success'" class="text success-text" key='a'>
            Done <i class="fas fa-check"></i>
          </span>
          <span class="text error-text" v-else-if="modifier === 'error'" key='b'>
            Error <i class="fas fa-exclamation-triangle"></i>
          </span>
          <span key="c" class="text loading-text" v-else-if="modifier === 'loading'">
            Please wait...
          </span>
          <span v-else class="text idle-text" key='d'>
            Button
          </span>
        </transition>
      </button>
    </div>
 
  </template>
  
  <br />
  <button class="btn btn-secondary"
          v-on:click="modifier=''">
    No State
  </button>
 
  <button class="btn btn-primary"
          v-on:click="modifier='loading'">
     Loading modifiers
  </button>
  
  <button class="btn btn-success" 
          v-on:click="modifier='success'">
     Success Modifiers
  </button>
  <button...

SCSS

@keyframes back-n-forth {
  from {
    left: -20%;
     width: 20px;
  }
  to {
  
    left: calc(120% - 20px);
  }
}

@keyframes infinite-load {
  0% {
    left: 0px;
    width: 0%;
  }
  50% {
    right: 0px;
    width: 100%;
  }
  100% {
    right: 0px;
    width: 0%;
   
  }
}

@keyframes zoom-out {
  from {
    transform: scale(1);
  }
  
  to {
    transform: scale(0.0);
  }
}


@keyframes pulse {
  from {
    box-shadow: inset 0px 0 10px rgba(255, 255, 255, 0.1);
    text-shaodw: 0 0 10xp rgba(0, 0, 0, 0.0);
  }
  
  to {
    text-shaodw: 0 0 10xp rgba(0, 0, 0, 1);
    box-shadow: inset 0 0 20px rgba(255, 255, 255, 0.8);
  }
}

@keyframes rotate {
  from {
    transform: rotate(0deg);
  }
  to {transform: rotate(360deg)}
}


.pb-btn { 

  &.btn-primary {
    background-color: orangered;
    border: darken(orangered, 10%) 1px solid;
  }
  
  &-loading {
    position: relative;  
  
    &.loading {
      &:after {
        content: "";
        display: block;
        background-color: white;
        opacity: 0.5;
        animation: back-n-forth 500ms infinite linear alternate;

        position: absolute;

        width: 20px;
        left: 0px;

        bottom: 0px;
        height: 5px;
      }
    }
    
    
  }
  
  &-loading-a {
    
    &.loading {
       position: relative;  
      animation: pulse 600ms infinite linear alternate;
      box-shadow: none; 
    }
   
  } 
 
  &-loading-b {
    position: relative;
    
    &.loading{
        &:after {
        content: "";
        display: block;
        background-color: rgba(255, 255, 255, 0.5);
        opacity: 1;
        animation: infinite-load 900ms ease-in-out infinite;

        position: absolute;

        width: 20px;


        bottom: 0px;
        height: 5px;
      }
    }
  }
  
  .loading-text {
      display: block;
      transition: transform 500ms;
      transform: scale(1);
  }
  
  transition: 500ms;
  width: 200px;
  
  &-loading-c {
    position: relative;
    
    &.loading {
      ...

Vue

var app = new Vue({
  el: '#main',
  props: {
    loadingClasses : {
        type: Array,
        default: () => (
        [
            'btn-loading', 
            'btn-loading-a', 
            'btn-loading-b',
            'btn-loading-c',
        ]
      )
    },
    enterAnimationClasses: {
        type: Array,
        default: () => ([
        	'bounceIn',
          'bounceIn',
          'bounceIn',
          'bounceIn',
        ])
    },
    leaveAnimationClasses: {
        type: Array,
        default: () => ([
        	'bounceOut',
          'bounceOut',
          'bounceOut',
          'bounceOut',
        ])
    },
    modifier: {
    	type: String,
      default: "",
    },
  	
  },
  data: {
    loading: true,
  }
})