JSFiddle - React, Tailwind, and code Playground
by secretgspot
HTML
<div class="inliner"></div>
<div class="inlined">
<div class="progress-meter">
<div class="track">
<span class="progress"></span>
</div>
<ol class="progress-points" data-current="4">
<li class="progress-point" data-point="1">
<span class="label">Lorem ipsum</span>
</li>
<li class="progress-point" data-point="2">
<span class="label">Aliquam tincidunt</span>
</li>
<li class="progress-point" data-point="3">
<span class="label">Vestibulum auctor</span>
</li>
<li class="progress-point" data-point="4">
<span class="label">Lorem ipsum</span></li>
<li class="progress-point" data-point="5">
<span class="label">Aliquam tincidunt</span>
</li>
</ol>
</div>
<div class="controls">
<button class="trigger">Toggle progress</button>
<p>Click any point to navigate to it directly</p>
</div>
</div>
SCSS
$points : 5;
$demo_w : 90%;
$track_h : 4px;
$track_h05 : $track_h / 2;
$gutter : 100% / ($points - 1);
$duration : 1s;
$_r : 24px;
$_r05 : $_r / 2;
$_r025 : $_r05 / 2;
$_b : $track_h;
$_mt : ($track_h - $_r) * 0.5 - $track_h;
$tint-track : #ddd;
$tint-progress : red;
$tint-complete : #777;
$tint-incomplete : lighten($tint-complete, 20%);
*, *:before, *:after {
@include box-sizing(border-box);
}
html, body {
height: 100%;
}
body {
font-size: 14px;
text-align: center;
}
.inliner {
height: 100%;
}
.inliner,
.inliner + .inlined {
display : inline-block;
vertical-align : middle;
}
.inlined {
width: $demo_w;
}
%demo {
margin : 20px auto 40px;
padding : 40px;
}
.progress-meter {
@extend %demo;
counter-reset : point;
%check {
@include transition;
@include border-radius($_r);
@include box-shadow(0 0 0 2px white);
content : "\2713";
display : block;
width : $_r;
margin : 0 auto $_r05;
border : $_b solid $tint-incomplete;
text-align : center;
background-color : white;
color : white;
}
.track {
position : relative;
height : $track_h;
background : $tint-track;
}
.progress {
@include transition(width 1s);
display : block;
position : absolute;
left : 0;
top : 0;
width : 0;
height : $track_h;
background : $tint-progress;
}
.progress-points {
position : relative;
margin : $_mt 0 0;
padding : 0;
list-style : none;
@for $i from 1 through $points {
[data-point='#{$i}'] {
left: ($i - 1) * $gutter;
}
}
}
.progress-point {
$_w : 100px;
$_ml: $_w / -2;
@include transition(color $duration);
position : absolute;
display : block;
width : $_w;
...
CoffeeScript
$trigger = $('.trigger').first()
$points = $('.progress-points').first()
$point_arr = $('[data-point]')
$progress = $('.progress').first()
# subtract 1 from values to zero index progress
val = parseInt($points.data 'current') - 1
max = $point_arr.length - 1
tracker = active = 0
# Helper method
activate = (index) ->
if index isnt active
active = index
$point_arr.removeClass('completed active')
$point_arr.slice(0, index).addClass 'completed'
$point_arr.eq(active).addClass 'active'
$progress.css 'width', (index / max * 100) + "%"
# UI event handlers
$points.on 'click', 'li', (event) ->
_index = $point_arr.index @
tracker = if _index is 0 then 1 else if _index is val then 0 else tracker
activate _index
$trigger.on 'click', -> activate(if tracker++ % 2 is 0 then 0 else val)
# Start the demo
setTimeout (-> activate val), 1000