JSFiddle - React, Tailwind, and code Playground

by jillztom

HTML

<script src="https://fonts.googleapis.com/css?family=Montserrat"></script>
<script src="https://unpkg.com/vue@latest/dist/vue.js"></script>
<div id="app">
  <p><user-link :user=user></user-link> created this tutorial!</p>
  <p>Hey there! visit us on <user-link :user=user2></user-link>! </p>
</div>

<script type="text/x-template" id="user-link-template">
  <div class="inline">
    	<a href="#" v-on:mouseover="hover" v-on:mouseout="hoverOut">{{ user.name }}</a>
      <div class="user-popover" v-if="showPopup" transition="fade" v-on:mouseover="hoverInfo" v-on:mouseout="hoverOutInfo">
      <h3>{{ user.name }}</h3>
      <button>Follow {{user.name}}</button>
    </div>
  </div>
</script>

CSS

body{
        font-family: 'Montserrat', sans-serif;
    }
    a{
        color: #42b983;
    }

    #app{
        height: 400px;
    }

    p{
        font-size: 14px;
    }
    h3{
        margin: 5px 0;
    }
    .is-flex{
        height: 100%;
        width: 100%;
        display: flex;
        flex-direction: column;
        align-items: center;
        justify-content: center;
    }
    .inline{
        display: inline-block;
        position: relative;
    }
    .user-popover{
        position: absolute;
        width: 200px;
        background: #fff;
        border: 1px solid #42b983;
        padding: 10px 20px;
        box-shadow: 0 6px 6px rgba(16, 16, 16, 0.04), 0 6px 6px rgba(0, 0, 0, 0.05);
        z-index:999;
    }

    button{
        background: #42b983;
        font-family: 'Montserrat', sans-serif;
        border: 1px solid #42b983;
        padding: 12px;
        font-size: 12px;
        color: #fff;
        outline: none;
        display: inline-block;
        text-align: center;
        padding: 6px 12px;
        border-radius: 3px;
        user-select: none;
        margin: 0 0 5px 0;
    }

JavaScript

Vue.component('user-link', {
  template: '#user-link-template',
  props: ['user'],
  data: function () {
    return {
			showPopup: false,
			timer: '',
			isInInfo: false
    }
  },
  
  methods: {

    hover: function()
    {
      let vm = this;
      this.timer = setTimeout(function() {
        vm.showPopover();
      }, 600);
    },

    hoverOut: function()
    {
      let vm = this;
      clearTimeout(vm.timer);
      this.timer = setTimeout(function() {
        if(!vm.isInInfo)
        {
          vm.closePopover();
        }
      }, 200);
    },

    hoverInfo: function()
    {
      this.isInInfo = true;
    },
    
    hoverOutInfo: function()
    {
      this.isInInfo = false;
      this.hoverOut();
    },

    showPopover: function()
    {
      this.showPopup = true;
    },

    closePopover: function()
    {
      this.showPopup = false;
    }
	}
})


new Vue({
	el: '#app',
  data: function(){
  	return { 
    	user: {name: 'Jilson Thomas'},
    	user2: {name: 'VueJobs.com'}
    }
  }
  
});