<div id="content" class="content">
<div class="container-fluid timeline">
<!-- ghost elements for background -->
<div class="row background">
<div class="col-lg-5 year-2018"></div>
<div class="col-lg-7 year-2019"></div>
</div>
<!-- ghost elements for background: END -->
<div class="container timeline__title">
<h2 class="section-heading">ROAD MAP</h2>
</div>
<div class="container years">
<div class="row">
<div class="col-lg-5">2018</div>
<div class="col-lg-7">2019</div>
</div>
</div>
<div class="timeline__points">
<div class="horizontal-line"></div>
<div class="container">
<div class="row">
<div class="col-lg-5 year-2018">
<!-- point -->
<div class="point"
v-for="(point, index) in timeline2018">
<div class="upper-content">
<div class="tooltip tooltip--top"
:ref="'tooltip2018' + index"
v-if="index % 2 != 0">
<ul>
<li v-for="task in point.points"
v-text="task">
</li>
</ul>
</div>
</div>
<div class="circle"
v-bind:class="{inThisQuarter: point.quarter == currentQuarter && year == 2018}"
v-text="point.quarter"
v-bind:ref="'circle2018' + index"
v-on:click="toggleTooltip(2018, index)">
</div>
<div class="bottom-content">
<div class="tooltip tooltip--bottom"
v-bind:ref="'tooltip2018' + index"
v-if="index % 2 == 0">
<ul>
<li v-for="task in point.points"
v-text="task">
</li>
</ul>
</div>
</div>
</div>
<!-- point: END-->
</div>
<div class="col-lg-7 year-2019">
<!-- point -->
<div class="point"
v-for="(point, index) in timeline2019">
<div class="upper-content">
<div class="tooltip tooltip--top"
v-bind:ref="'tooltip2019' + index"
v-if="index % 2 != 0">
<ul>
<li v-for="task in point.points"
v-text="task">
</li>
</ul>
</div>
</div>
<div class="circle"
v-bind:class="{inThisQuarter: point.quarter == currentQuarter && year == 2019}"
v-text="point.quarter"
v-bind:ref="'circle2019' + index"
v-on:click="toggleTooltip(2019, index)">
</div>
<div class="bottom-content">
<div class="tooltip tooltip--bottom"
v-bind:ref="'tooltip2019' + index"
v-if="index % 2 == 0">
<ul>
<li v-for="task in point.points"
v-text="task">
</li>
</ul>
</div>
</div>
</div>
<!-- point: END-->
</div>
</div>
</div>
</div>
</div>
</div>
@import url(https://fonts.googleapis.com/css?family=Roboto);
@mixin flex($dir, $jus: flex-start, $ali: flex-start, $wrap: nowrap) {
display: flex;
flex-direction: $dir;
justify-content: $jus;
align-items: $ali;
flex-wrap: $wrap;
}
$timeline-container-h: 640px;
$point-w: 120px;
$point-h: 300px;
$circle-size: 48px;
$primary-accent-dark: #7652D2;
$secondary-accent-dark: #9B75DE;
$easing: cubic-bezier(0.19, 1, 0.22, 1);
%pulsing-1 {
animation: pulsing-1 2s $easing infinite alternate;
@keyframes pulsing-1 {
from {transform: scale(1);}
to {transform: scale(1.7);}
}
}
%pulsing-2 {
animation: pulsing-2 2s $easing infinite alternate;
@keyframes pulsing-2 {
from {transform: scale(1);}
to {transform: scale(2.1);}
}
}
body {
margin: 0;
padding: 0;
overflow-x: hidden;
font-family: 'Roboto';
}
.section-heading {
color: white;
font-size: 48px;
font-weight: 520;
}
.years {
color: white;
font-size: 36px;
font-weight: 520;
}
.content {
background: black;
min-height: 100vh;
@include flex(row, center, center);
}
.timeline {
background: $primary-accent-dark;
height: $timeline-container-h;
padding: 36px 0;
position: relative;
margin: 128px 0;
.background {
width: 100%;
height: inherit;
position: absolute;
top: 0;
left: 1.1%;
.year-2018 {
background-color: $primary-accent-dark;
}
.year-2019 {
background-color: $secondary-accent-dark;
}
}
&__title, &__years, &__points {
position: relative;
z-index: 0;
}
&__points {
// background: rgba(100, 100, 100, 0.5);
height: $point-h;
.year-2018, .year-2019 {
@include flex(row, space-evenly);
}
}
.horizontal-line {
background: white;
width: 100%;
height: 4px;
position: absolute;
top: 50%;
}
}
.point {
width: $point-w;
height: $point-h;
@include flex(column, space-between, center);
position: relative;
z-index: 4;
.upper-content {
width: 100%;
height: ($point-h * 0.5) - $circle-size;
@include flex(column, flex-end);
strong {
color: white;
font-size: 24px;
margin-bottom: 24px;
}
}
.bottom-content {
width: 100%;
// height: calc(#{$point-h} * 0.5 - #{$circle-size});
height: ($point-h * 0.5) - $circle-size;
@include flex(column, flex-start);
}
}
.circle {
background: orange;
width: $circle-size;
height: $circle-size;
@include flex(row, center, center);
border: 6px solid white;
border-radius: 50%;
color: white;
font-weight: bold;
box-shadow: 0 2px 2px 5px rgba(238, 145, 36, 0.2);
&::before, &::after {
content: '';
display: inline-block;
width: $circle-size;
height: $circle-size;
border: 4px solid transparent;
border-radius: inherit;
position: absolute;
transition: all 0.5s ease-out;
opacity: 0;
}
&::before {
background: rgba(255, 255, 255, 0.25);
z-index: -1;
}
&::after {
background: rgba(255, 255, 255, 0.15);
z-index: -2;
}
&.inThisQuarter {
&::before {
opacity: 1;
@extend %pulsing-1;
}
&::after {
opacity: 1;
@extend %pulsing-2;
}
}
&.active {
border-color: orange;
&::before {
animation: none;
}
&::after {
animation: none;
background-color: transparent;
border-color: white;
transform: scale(1.7);
opacity: 1;
}
}
&:hover {
cursor: pointer;
}
}
.tooltip {
background-color: white;
width: 300px;
padding: 8px 4px;
border-radius: 16px;
transition: all 0.3s;
opacity: 0;
position: absolute;
left: -74%;
z-index: -3;
&.active {
opacity: 1;
}
&--top {
margin-top: -10%;
margin-bottom: 10%;
&::before {
content: '';
display: inline-block;
background: white;
width: 5px;
height: 24px;
position: absolute;
bottom: -24px;
left: 49%;
}
}
&--bottom {
margin-top: 10%;
&::before {
content: '';
display: inline-block;
background: white;
width: 5px;
height: 24px;
position: absolute;
top: -24px;
left: 49%;
}
}
}
View Compiled
var timeline2018 = [
{
quarter: 'Q3',
points: [
'Website launch',
'Whitepaper release',
'TOKOIN token distributions starts',
'TOKOIN Wallet development'
]
},
{
quarter: 'Q4',
points: [
'POC Launch on TestNet',
'Onboard logistic partners on Tokoin ecosystem'
]
}
];
var timeline2019 = [
{
quarter: 'Q1',
points: [
'Launch dApps on MainNet',
'Onboard Warehousing partners on Tokoin ecosystem',
'Onboard Financial partners on Tokoin ecosystem',
'Expand local operation to 10 tier-one cities in Indonesia',
'Onboard 50.000 users on Tokoin ecosystem'
]
},
{
quarter: 'Q2',
points: [
'Launch Data Reputation engine',
'Launch Data Visualization platform',
'Launch Partner Suite platform'
]
},
{
quarter: 'Q3',
points: [
'Launch TOKOIN POS system',
'Launch Data Exchange platform for Token Stacking and Loyalty program',
'Expand local operation to all capital cities in Indonesia',
'Onboard 10.000 users for TOKOIN POS system'
]
},
{
quarter: 'Q4',
points: [
'Expand hyper-local operation to Thailand, Vietnam, Philippine, Malaysia and other potential emerging market'
]
}
];
var date = new Date();
var month = date.getMonth();
var year = date.getFullYear();
var vm = new Vue({
el: '#content',
data: {
timeline2018: timeline2018,
timeline2019: timeline2019,
month: month,
year: year
},
computed: {
currentQuarter: function() {
if(this.month >= 0 && this.month <= 2) return 'Q1';
else if(this.month >= 3 && this.month <= 5) return 'Q2';
else if(this.month >= 6 && this.month <= 8) return 'Q3';
return 'Q4';
}
},
methods: {
normalizeSelection(year, idx) {
var circ, tooltip, yearTemp = 2018, j = 0;
for(var i = 0; i < 6; i++) {
if(i > 1) {
yearTemp = 2019;
j = 0;
}
if(j != idx) {
circ = this.$refs['circle'+yearTemp+j][0];
tooltip = this.$refs['tooltip'+yearTemp+j][0];
circ.classList.remove('active');
tooltip.classList.remove('active');
}
j++;
}
},
toggleTooltip(year, idx) {
var circ = this.$refs['circle'+year+idx][0];
console.log(circ);
var tooltip = this.$refs['tooltip'+year+idx][0];
if(!circ.classList.contains('active')) {
circ.classList.add('active');
tooltip.classList.add('active');
} else {
circ.classList.remove('active');
tooltip.classList.remove('active');
}
},
}
});