JSFiddle - React, Tailwind, and code Playground

by CristiJ

HTML

<link rel="stylesheet" href="https://rawgit.com/lykmapipo/themify-icons/master/css/themify-icons.css">
<link rel="stylesheet" href="https://rawgit.com/cristijora/vue-form-wizard/master/dist/vue-form-wizard.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.2.6/vue.min.js"></script>
<script src="https://rawgit.com/cristijora/vue-form-wizard/master/dist/vue-form-wizard.js"></script>
<div id="app">
<div>
    <form-wizard @on-complete="onComplete"
                @on-loading="setLoading"
                @on-validate="handleValidation"
                @on-error="handleErrorMessage"
                shape="circle"
                color="gray"
                error-color="#e74c3c">
      <tab-content title="Personal details"
                   :before-change="validateAsync"
                   icon="ti-user">
              First tab
      </tab-content>
      <tab-content title="Additional Info"
                   icon="ti-settings">
              Second tab
      </tab-content>
      <tab-content title="Last step"
                   icon="ti-check">
              Third tab
      </tab-content>
      
      <div class="loader" v-if="loadingWizard"></div>
      <div v-if="errorMsg">
        <span class="error">{{errorMsg}}</span>
      </div>
    </form-wizard>
 </div>
</div>

CSS

span.error{
  color:#e74c3c;
  font-size:20px;
  display:flex;
  justify-content:center;
}
/* This is a css loader. It's not related to vue-form-wizard */
.loader,
.loader:after {
  border-radius: 50%;
  width: 10em;
  height: 10em;
}
.loader {
  margin: 60px auto;
  font-size: 10px;
  position: relative;
  text-indent: -9999em;
  border-top: 1.1em solid rgba(255, 255, 255, 0.2);
  border-right: 1.1em solid rgba(255, 255, 255, 0.2);
  border-bottom: 1.1em solid rgba(255, 255, 255, 0.2);
  border-left: 1.1em solid #e74c3c;
  -webkit-transform: translateZ(0);
  -ms-transform: translateZ(0);
  transform: translateZ(0);
  -webkit-animation: load8 1.1s infinite linear;
  animation: load8 1.1s infinite linear;
}
@-webkit-keyframes load8 {
  0% {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}
@keyframes load8 {
  0% {
    -webkit-transform: rotate(0deg);
    transform: rotate(0deg);
  }
  100% {
    -webkit-transform: rotate(360deg);
    transform: rotate(360deg);
  }
}

JavaScript

Vue.use(VueFormWizard)
new Vue({
 el: '#app',
 data:{
    loadingWizard: false,
    errorMsg: null,
    count: 0
 },
 methods: {
  onComplete: function(){
      alert('Yay. Done!');
   },
   setLoading: function(value) {
       this.loadingWizard = value
   },
   handleValidation: function(isValid, tabIndex){
      console.log('Tab: '+tabIndex+ ' valid: '+isValid)
   },
   handleErrorMessage: function(errorMsg){
     this.errorMsg = errorMsg
   },
   validateAsync:function() {
     return new Promise((resolve, reject) => {
       setTimeout(() => {
         if(this.count < 1){
          this.count ++
         	reject('This is a custom validation error message. Click next again to get rid of the validation')
         }else{
          this.count = 0
          resolve(true)
         }   
       }, 1000)
     })
    },
  }
})