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">
<div id="reactions">
<react class="react-button" name="yes" :count="35">
<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 class="react-count" #count="{count: count}">
<div class="react-count">{{ count }}</div>
</template>
</react>
<react class="react-button" name="maybe" :count="10">
<div class="react-icon">
<svg class="svg-symbol"><use xlink:href="#maybe"/></svg>
<div class="loading"></div>
</div>
<div class="react-text">Vielleicht</div>
<template class="react-count" #count="{count: count}">
<div class="react-count">{{ count }}</div>
</template>
</react>
<react class="react-button" name="no" :count="23">
<div class="react-icon">
<svg class="svg-symbol"><use xlink:href="#thumb-down"/></svg>
<div class="loading"></div>
</div>
<div class="react-text">Nein</div>
<template class="react-count" #count="{count: count}">
<div class="react-count">{{ count }}</div>
</template>
</react>
</div>
</div>
<script type="text/x-template" id="react-button">
<button @click="react" :class="{'reaction-loaded': loading}" :disabled="loading">
<slot>{{ name }}</slot>
<slot name="count" :count="count">[{{ count }}]</slot>
</button>
</script>
<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...
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: {
type: String,
value: 'React',
},
},
data: function () {
return {
loading: false,
currentCount: 0,
}
},
template: '#react-button',
computed: {
count: {
get: function() {
return this.currentCount;
},
set: function(value) {
this.currentCount = value;
}
},
},
methods: {
react: function(){
var _this = this,
min = 150,
max = 300,
randomNumber = Math.floor(Math.random() * max) + min;
_this.loading = true;
axios.post('/echo/json/', {count: _this.name}).then(function (response) {
setTimeout(function(){
_this.count++;
_this.loading = false;
console.log( response.data );
}, randomNumber);
}).catch(function (error) {
//console.log(error);
}).then(function () {
//console.log('every time');
});
}
}
});
new Vue({
el: '#app'
});