JSFiddle - React, Tailwind, and code Playground

by NOVUSIDEA

HTML

<script src="https://unpkg.com/[email protected]/dist/axios.js"></script>
<script src="https://unpkg.com/[email protected]/dist/vue.js"></script>
<div id="app">

    <react class="react-button" name="yes"></react>

    <div id="reactions">
        <react class="react-button" name="yes">
        
            <div class="react-icon">
                <svg class="svg-symbol"><use xlink:href="#thumb-up"/></svg>
                <div class="loading"></div>
            </div>
            
            <div class="react-text">Ja</div>
            
            <template #count="count"></template>
            
        </react>

        <react class="react-button" name="maybe">
            <div class="react-icon">
                <svg class="svg-symbol"><use xlink:href="#maybe"/></svg>
                <div class="loading"></div>
            </div>
            <div>Vielleicht</div>
        </react>

        <react class="react-button" name="no">
            <div class="react-icon">
                <svg class="svg-symbol"><use xlink:href="#thumb-down"/></svg>
                <div class="loading"></div>
            </div>
            <div>Nein</div>
        </react>
    </div>



</div>

<svg style="display:none">
    <symbol id="maybe" viewBox="0 0 24 24">
        <title>maybe</title>
        <path d="m11.979 2.0017c-1.395-0.06335-2.4009 1.6346-1.6774 2.8278 0.61323 1.2546 2.5854 1.3245 3.2859 0.11636 0.83097-1.2153-0.13243-2.9865-1.6084-2.9441zm-6.1245 4.3155c-1.0142-0.20321-1.4623 1.1263-0.76746 1.7487 0.49887 0.71496 0.94383 1.4718 1.4803 2.1575 0.76398 0.74649 1.8077 0.1298 2.3482-0.55971 0.31089-0.15681 1.1214-1.3354 0.9921-0.47874-0.013751 1.3381 0.027495 2.6801-0.020596 4.0158-0.3534 2.5584-0.72855 5.1144-1.0683 7.6743-0.066858 0.90825 1.1377 1.4826 1.8011 0.84216 0.50304-0.49485 0.40683-1.2573 0.56811-1.8973 0.263-1.5961 0.52599-3.1923 0.78897-4.7883 0.34722 2.0758 0.66633 4.1577 1.0313 6.2298 0.25243 0.95547 1.7529 0.99372 2.0496 0.05775...

CSS

* {
    box-sizing: border-box;
}

#reactions {
    display: flex;
    justify-content: space-around;
}

.react-button {
    background: beige;
    cursor: pointer;
    padding: 0;
    border: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    flex: 0 0 30%;
    max-width: 30%;
    font-size: 18px;
}

.react-button:disabled {
    opacity: 0.5;
}

.react-icon {
    font-size: 50px;
}

.svg-symbol {
    display: block;
    width: 1em;
    height: 1em;
}

.react-button .loading {
    position: relative;
    display: block;
    width: 1em;
    height: 1em;
    display: none;
}

.react-button .loading::before {
    content: ' ';
    position: absolute;
    top: 0.15em;
    left: 0.15em;
    right: 0.15em;
    bottom: 0.15em;
    border: 0.1em solid currentColor;
    border-bottom-color: transparent;
    border-radius: 1em;
    animation-name: spin;
    animation-duration: 0.8s;
    animation-timing-function: linear;
    animation-iteration-count: infinite;
}

.react-button.reaction-loaded .svg-symbol {
    display: none;
}

.react-button.reaction-loaded .loading {
    display: block;
}

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

JavaScript

Vue.component('react', {
	props: {
    	name: String,
        count: Number,
        loading: Boolean,
    },
    data: function () {
        return {
            count: 0,
        }
    },
	template: '<button @click="react" :class="{\'reaction-loaded\': loading}" :disabled="loading"><slot></slot><slot name="count">{{ count }}</slot></button>',
    methods: {
    	react: function(){
        
        	var _this = this,
            	min = 150,
                max = 300,
            	randomNumber = Math.floor(Math.random() * max) + min;
            _this.loading = true;
            
            console.log( randomNumber );
            
            axios.post('/echo/json/', {count: this.name}).then(function (response) {
            
            	setTimeout(function(){
                	_this.count++;
           			_this.loading = false;
                    console.log( response );
                }, randomNumber);
                
            }).catch(function (error) {
            
                //console.log(error);
                
            }).then(function () {
                
                //console.log('every time');
                
            });  

        }
    }
});

new Vue({
    el: '#app'
});