JSFiddle - React, Tailwind, and code Playground

by samur3

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<div id="app-container" ng-app="app">
  <widget></widget>
</div>

SCSS

widget {
  display: block;
  box-sizing: border-box;
  width: 500px;
  padding: 15px;
  background: #fff;
  border: 1px solid #ddd;
  border-radius: 3px;
  font-family: sans-serif;
  margin: 100px auto;
  h3 {
    margin: 0;
    font-size: 1em;
  }
}
widget bar {
  display: block;
  width: 100%;
  margin-bottom: 50px;
  margin-top: 20px;
  .bar-container {
    width: 100%;
    .bar-section {
      display: inline-block;
      position: relative;
      margin-top: 30px;
      height: 30px;
      color: #fff;
      padding: 0 10px;
      box-sizing: border-box;
      vertical-align: middle;
      -o-user-select: none;
      -ms-user-select: none;
      -moz-user-select: none;
      -webkit-user-select: none;
      user-select: none;
      cursor: default;
      transition: height .3s ease-in-out, margin-top .3s ease-in-out, border-bottom-width .2s ease-in-out;
      .bar-title {
        display: inline-block;
        width: 100%;
        white-space: nowrap;
        text-align: center;
        line-height: 30px;
        transition: line-height .3s ease-in-out;
        overflow: hidden;
        text-overflow: ellipsis;
      }
      &.active {
        margin-top: 0;
        height: 60px;
        border-bottom: 5px solid rgba(0, 0, 0, .3);
        .bar-title {
          line-height: 60px;
        }
      }
    }
  }
}
widget bar .bar-container .bar-section .tooltip {
  position: absolute;
  display: inline-block;
  width: 200px;
  height: 0;
  left: calc(50% - 100px);
  top: -20px;
  text-align: center;
  transition: height .3s ease-in-out, top .3s ease-in-out, padding .3s ease-in-out;
  overflow: hidden;
  .tooltip-content {
    position: relative;
    display: inline-block;
    width: 100%;
    height: calc(100% - 10px);
    background: #000;
    padding: 15px;
    box-sizing: border-box;
    border-bottom: 5px solid #ccc;
    &::after {
      content: '';
      position: absolute;
      left: calc(50% - 10px);
      bottom: -15px;
      border-top: 10px solid...

JavaScript

angular.module('app', [])
.component('bar', {
	template: `
  	<div class='bar-container'>
    	<div class='bar-section' 
      		 ng-repeat='item in $ctrl.data'
           ng-style='{width: $ctrl.calculateWidth(item), background: item.color}'
           ng-class='{active: $index === $ctrl.active}'
           ng-click='$ctrl.active = $ctrl.active === $index ? -1: $index'>
      	<span class='bar-title'>{{item.text}}</span>
        <span class='tooltip'>
        	<span class='tooltip-content'>
        		{{item.text}}
          </span>
        </span>
      </div>
    </div>
  `,
  controller: function() {
    this.calculateWidth = (item) => {
    	return `${100 / this.data.reduce((sum, next) => sum + next.value, 0) * item.value}%`;
    };
  },
  bindings: {
  	data: '<'
  }
})
.component('widget', {
	template: `
  	<h3>{{$ctrl.item.title}}</h3>
		<bar data='$ctrl.item.data'></bar>
  `,
  controller: function() {
  	this.item = {
    	title: 'Attributes',
      data: [
        {value: 2, text: 'ssn (0%)', color: '#ea2'},
        {value: 3, text: 'full_name (0%)', color: '#dd0'},
        {value: 1, text: 'zipcode123 (0%)', color: '#5c6'}
      ]
    }
  }
})