Skip to content

Commit

Permalink
Add circular progress bar
Browse files Browse the repository at this point in the history
  • Loading branch information
javivelasco committed Jul 4, 2015
1 parent e58acd1 commit 2e811f3
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 48 deletions.
42 changes: 30 additions & 12 deletions components/progress_bar/index.cjsx
@@ -1,5 +1,9 @@
###
@todo Add a circular progress variant
@todo
v2
- can set different sizes for circular progress
- maybe a multicolor indeterminate circular progress bar
- refactor vendor prefixes adding to a module
###

require './style'
Expand All @@ -10,17 +14,19 @@ module.exports = React.createClass
propTypes:
buffer : React.PropTypes.number
className : React.PropTypes.string
indeterminate : React.PropTypes.bool
max : React.PropTypes.number
min : React.PropTypes.number
mode : React.PropTypes.string
type : React.PropTypes.string
value : React.PropTypes.number

getDefaultProps: ->
buffer : 0
className : ""
indeterminate : false
className : ''
max : 100
min : 0
mode : 'indeterminate'
type : 'linear'
value : 0

# -- Helper methods
Expand All @@ -29,22 +35,34 @@ module.exports = React.createClass

# -- Render
render: ->
className = @props.className
className += ' indeterminate' if @props.indeterminate
valueStyle = transformProgress(@calculateRatio(@props.value))
bufferStyle = transformProgress(@calculateRatio(@props.buffer))

<div data-component-progressbar
className = "#{@props.type} #{@props.className} #{@props.mode}"
<div data-component-progressbar role="progressbar"
className={className}
role="progressbar"
aria-valuenow={@props.value}
aria-valuemin={@props.min}
aria-valuemax={@props.max}>
{ if @props.type == 'circular' then @renderCircular() else @renderLinear() }
</div>

renderCircular: ->
style = transformDasharray(@calculateRatio(@props.value)) unless @props.mode == 'indeterminate'
<svg data-component-progressbar-circle>
<circle style={style} data-component-progressbar-circle-path cx="50" cy="50" r="45"/>
</svg>

renderLinear: ->
unless @props.mode == 'indeterminate'
bufferStyle = transformProgress(@calculateRatio(@props.buffer))
valueStyle = transformProgress(@calculateRatio(@props.value))
<div>
<span data-component-progressbar-buffer style={bufferStyle}></span>
<span data-component-progressbar-value style={valueStyle}></span>
</div>

# TODO Refactor to a module to add vendor prefixes to a property
# -- Private methods
transformDasharray = (ratio) ->
strokeDasharray: "#{2 * Math.PI * 45 * ratio}, 400"

transformProgress = (ratio) ->
WebkitTransform: "scaleX(#{ratio})"
MsTransform: "scaleX(#{ratio})"
Expand Down
117 changes: 83 additions & 34 deletions components/progress_bar/style.styl
@@ -1,40 +1,89 @@
@import '../constants.styl'

// -- Main styles
// -- NOTE: Parameters depend on the component SVG Markup too
CIRCLE_WRAPPER_WIDTH = 100
CIRCLE_RADIUS = 45
SCALE_RATIO = CIRCLE_RADIUS/20

[data-component-progressbar]
display : inline-block
position : relative
height : PROGRESS_BAR_HEIGHT
width : 100%
background : darken(BACKGROUND, 7.5%)
overflow : hidden

[data-component-progressbar-value], [data-component-progressbar-buffer]
position : absolute
bottom : 0
left : 0
right : 0
top : 0
transform scaleX(0)
transform-origin left center
transition-duration ANIMATION_DURATION
transition-timing-function ANIMATION_EASE

[data-component-progressbar-value]
background-color : SECONDARY

[data-component-progressbar-buffer]
background-color : alpha(SECONDARY, 15%)

&.indeterminate > [data-component-progressbar-value]
transform-origin center center
animation indeterminate-bar 1s linear infinite

// -- Animation for the indeterminate progress bar
@keyframes indeterminate-bar
display : inline-block

&.linear
position : relative
height : PROGRESS_BAR_HEIGHT
width : 100%
background : darken(BACKGROUND, 7.5%)
overflow : hidden

[data-component-progressbar-value], [data-component-progressbar-buffer]
position : absolute
bottom : 0
left : 0
right : 0
top : 0
transform scaleX(0)
transform-origin left center
transition-duration ANIMATION_DURATION
transition-timing-function ANIMATION_EASE

[data-component-progressbar-value]
background-color : SECONDARY

[data-component-progressbar-buffer]
background-color : alpha(SECONDARY, 15%)

&.indeterminate [data-component-progressbar-value]
transform-origin center center
animation linear-indeterminate-bar 1s linear infinite

&.circular
position : relative
height : CIRCLE_WRAPPER_WIDTH * 1px
width : CIRCLE_WRAPPER_WIDTH * 1px
transform rotate(-90deg)

[data-component-progressbar-circle]
height : 100%
width : 100%

[data-component-progressbar-circle-path]
stroke-dasharray : 0, SCALE_RATIO * 200
stroke-dashoffset : 0
stroke-linecap : round
stroke-miterlimit : 20
stroke-width : 4
stroke : SECONDARY
fill : none
transition stroke-dasharray ANIMATION_DURATION ANIMATION_EASE

&.indeterminate
[data-component-progressbar-circle]
animation circular-indeterminate-bar-rotate 2s linear infinite

[data-component-progressbar-circle-path]
stroke-dasharray : SCALE_RATIO * 1, SCALE_RATIO * 200
stroke-dashoffset : 0
animation circular-indeterminate-bar-dash 1.5s ease-in-out infinite

@keyframes linear-indeterminate-bar
0%
transform translate(-50%) scaleX(0)
50%
transform translate(-0%) scaleX(0.3)
100%
transform translate(50%) scaleX(0)

@keyframes circular-indeterminate-bar-rotate
100%
transform : rotate(360deg)

@keyframes circular-indeterminate-bar-dash
0%
transform: translate(-50%) scaleX(0)
stroke-dasharray : SCALE_RATIO * 1, SCALE_RATIO * 200
stroke-dashoffset : SCALE_RATIO * 0
50%
transform: translate(0%) scaleX(0.3)
stroke-dasharray : SCALE_RATIO * 89, SCALE_RATIO * 200
stroke-dashoffset : SCALE_RATIO * -35
100%
transform: translate(50%) scaleX(0)
stroke-dasharray : SCALE_RATIO * 89, SCALE_RATIO * 200
stroke-dashoffset : SCALE_RATIO * -124
7 changes: 5 additions & 2 deletions spec/components/progress.cjsx
Expand Up @@ -38,8 +38,11 @@ module.exports = React.createClass
<h2>Progress bars</h2>

<p>Determinate</p>
<ProgressBar value={@state.progress} buffer={@state.buffer}/>
<ProgressBar mode="determinate" value={@state.progress} buffer={@state.buffer}/>

<p>Indeterminate...</p>
<ProgressBar indeterminate={true}/>
<ProgressBar mode="indeterminate"/>

<p>Circular</p>
<ProgressBar type="circular" mode="indeterminate"/>
</section>

0 comments on commit 2e811f3

Please sign in to comment.