JSFiddle - React, Tailwind, and code Playground
by Mike Jacobson
HTML
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.css">
<div ng-app="myapp">
<timeline>
</timeline>
</div>
CSS
.timeline-simple {
font-size: 10px;
height: 150px;
overflow-x: scroll;
white-space: nowrap;
}
.timeline-simple .timeline-bar {
background-color: #ddd;
bottom: 2px;
height: 4px;
position: relative;
top: 100px;
width: 100%;
}
.timeline-simple ol {
padding: 80px 0 20px 20px;
position: relative;
//width: 100vw;
}
.timeline-simple ol li {
display: block;
list-style-type: none;
position: absolute;
white-space: normal;
width: 170px;
&::before { // line
background: #ddd;
bottom: -10px;
content: '';
display: block;
height: 20px;
left: calc(20% + 2px);
position: absolute;
width: 2px;
}
&::after { // dot
background: #fff;
border: 1px solid #ddd;
border-radius: 50%;
bottom: 0;
content: '';
height: 10px;
left: 14px;
position: absolute;
top: 2px;
width: 10px;
}
}
.timeline-simple-item {
background-color: transparent;
border: 1px solid #ddd;
border-right-color: transparent;
position: relative;
height: 120px;
}
.timeline-simple-item-upper-left {
border: 1px solid #ddd;
border-left-color: #fff;
border-top-color: #fff;
height: 90px;
left: -1px;
width: 67%;
position: absolute;
top: -1px;
}
.timeline-simple-item-content {
background-color: #fff;
border: 1px solid #ddd;
height: 50px;
left: calc(67% - 20px);
position: absolute;
top: -1px;
width: 80px;
}
.timeline-simple .fa-circle {
font-size: 6px;
}
JavaScript
angular.module('myapp', [])
.directive('timeline', timeline)
var data = [
{ dueDateValue: 1470034800000, display: '08/01/2016' },
{ dueDateValue: 1470034800000, display: '08/01/2016' },
{ dueDateValue: 1479628800000, display: '11/20/2016' },
{ dueDateValue: 1486195200000, display: '02/04/2017' },
{ dueDateValue: 1492153200000, display: '04/14/2017' },
{ dueDateValue: 1493881200000, display: '05/04/2017' },
{ dueDateValue: 1505113200000, display: '09/11/2017' },
{ dueDateValue: 1506322800000, display: '09/25/2017' },
{ dueDateValue: 1506668400000, display: '09/29/2017' },
{ dueDateValue: 1507014000000, display: '10/03/2017' },
{ dueDateValue: 1507359600000, display: '10/07/2017' },
{ dueDateValue: 1520755200000, display: '03/11/2018' },
{ dueDateValue: 1528700400000, display: '06/11/2018' }
];
var first = data[0].dueDateValue;
var last = data[data.length - 1].dueDateValue;
var range = last - first;
data.forEach(function(o) {
o.offsetPercent = (((o.dueDateValue - first) / range) * 100) + '%';
});
function TimelineCtrl() {
var ctrl = this;
this.data = data;
}
function timeline() {
return {
restrict: 'E',
template: `
<div class="timeline-simple">
<div class="timeline-bar"></div>
<ol>
<li ng-repeat="m in ctrl.data"
ng-style="{ 'left': m.offsetPercent }">
<div class="timeline-simple-item">
<div class="timeline-simple-item-upper-left"></div>
<div class="timeline-simple-item-content">{{ m.offsetPercent }}</div>
</div>
</li>
</ol>
</div>
`,
controller: TimelineCtrl,
controllerAs: 'ctrl'
}
}