Skip to content

Commit

Permalink
Rewrite ripple in ES6 and update its dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
javivelasco committed Sep 18, 2015
1 parent 736fce8 commit 44cab7f
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 51 deletions.
20 changes: 7 additions & 13 deletions components/dropdown/index.cjsx
Expand Up @@ -26,7 +26,6 @@ module.exports = React.createClass

getInitialState: ->
active : false
ripple : undefined
selected : _selectValue @props.value, @props.dataSource

# -- Lifecycle
Expand All @@ -39,20 +38,15 @@ module.exports = React.createClass

# -- Events
onSelect: (event) ->
@setState active: true, ripple: undefined unless @props.disabled
@setState active: true unless @props.disabled

onItem: (event) ->
onItem: (id, event) ->
unless @props.disabled
client = event.target.getBoundingClientRect?()
value = event.target.getAttribute('id').toString()
value = id.toString()
for item in @props.dataSource when item.value.toString() is value
@setState
active : false
selected : item
ripple :
left : event.pageX - client?.left
top : event.pageY - client?.top
width : (client?.width * 2)
break

# -- Render
Expand All @@ -66,12 +60,12 @@ module.exports = React.createClass

<div data-react-toolbox='dropdown' className={className}>
{ <label>{@props.label}</label> if @props.label }
<ul ref='values' className={localCSS.values} style={stylesheet} onClick={@onItem}>
<ul ref='values' className={localCSS.values} style={stylesheet}>
{
for item, index in @props.dataSource
<li id={item.value} key={index} className={'selected' if item.value is @state.selected.value}>
{ if @props.template then @props.template item else item.label }
{ <Ripple className={localCSS.ripple} origin={@state.ripple}/> if item.value is @state.selected.value }
<li id={item.value} onClick={@onItem.bind(@, item.value)} key={index} style={{position: 'relative'}} className={'selected' if item.value is @state.selected.value}>
{if @props.template then @props.template item else item.label }
{ <Ripple className={localCSS.ripple}/> }
</li>
}
</ul>
Expand Down
11 changes: 5 additions & 6 deletions components/dropdown/style.styl
Expand Up @@ -26,10 +26,6 @@
cursor : pointer
&.selected
color : PRIMARY
> *
pointer-events : none
> :local(.ripple)
background-color : DIVIDER

:local(.value)
display : block
Expand Down Expand Up @@ -74,8 +70,6 @@
opacity : 1
transition : opacity ANIMATION_DURATION ANIMATION_EASE
&:not(.active)
> ul
pointer-events : none
> *, > * > li
transition-delay : ANIMATION_DURATION

Expand All @@ -99,3 +93,8 @@
bottom : -(SPACE / 4)
font-size : FONT_SIZE_TINY
color : TEXT_SECONDARY

:local(.ripple)
background-color : DIVIDER
opacity : 1
z-index : Z_INDEX_LOW
77 changes: 77 additions & 0 deletions components/ripple/index.jsx
@@ -0,0 +1,77 @@
/* global React */

import { addons } from 'react/addons';
import style from './style';

export default React.createClass({
mixins: [addons.PureRenderMixin],

displayName: 'Ripple',

propTypes: {
auto: React.PropTypes.bool,
className: React.PropTypes.string,
loading: React.PropTypes.bool
},

getDefaultProps () {
return {
auto: true,
className: '',
loading: false
};
},

getInitialState () {
return {
active: false,
restarting: false,
top: null,
left: null,
width: null
};
},

start ({ pageX, pageY }) {
const {top, left, width} = this._getDescriptor(pageX, pageY);
this.setState({active: false, restarting: true, width: 0}, () => {
this.refs.ripple.getDOMNode().offsetWidth; //eslint-disable-line no-unused-expressions
this.setState({active: true, restarting: false, top: top, left: left, width: width});
});
},

end () {
this.setState({active: false});
},

_getDescriptor (pageX, pageY) {
let { left, top, width } = this.getDOMNode().getBoundingClientRect();
return {
left: pageX - left,
top: pageY - top,
width: width * 2.5
};
},

render () {
let { left, top, width } = this.state;
let className = `${style.ripple} ${this.props.className}`;
if (this.state.active) className += ' active';
if (this.state.restarting) className += ' restarting';
if (this.props.loading) className += ' loading';

return (
<span
className={style.root}
onMouseDown={this.props.auto ? this.start : null}
onMouseUp={this.end}>

<span
ref="ripple"
className={className}
style={{left: left, top: top, width: width, height: width}}>
</span>
</span>
);
}
});
47 changes: 32 additions & 15 deletions components/ripple/style.styl
@@ -1,30 +1,47 @@
@import '../constants'

FINAL_OPACITY = .4

:local(.root)
position : absolute
background-color : alpha(WHITE, 0.65)
transform translateX(-50%) translateY(-50%)
top : 0
left : 0
right : 0
bottom : 0

:local(.ripple)
position : absolute
background-color : currentColor
transform : translateX(-50%) translateY(-50%)
border-radius : 50%
width : SIZE = (4 * UNIT)
height : SIZE
pointer-events : none
opacity : 0
// -- Classes
&.active, &.loading
animation-name ripple
animation-timing-function ANIMATION_EASE
animation-duration (2 * ANIMATION_DURATION)
&.active
animation-iteration-count 1
width : 0
height : 0
opacity : FINAL_OPACITY
transition-duration : 1.4 * ANIMATION_DURATION
transition-property : height, width

&:not(.active).restarting
transition-property : none

&:not(.active)
opacity : 0
transition-property : opacity, height, width

&.loading
animation-name : ripple
animation-iteration-count : infinite
animation-timing-function : ANIMATION_EASE
animation-duration : (2 * ANIMATION_DURATION)
height : (4 * UNIT)
width : (4 * UNIT)
left : 50%
opacity : 0
top : 50%
animation-iteration-count infinite

@keyframes ripple
0%
width : 0
height : 0
opacity : 1
opacity : FINAL_OPACITY
100%
opacity : 0
4 changes: 0 additions & 4 deletions components/switch/index.cjsx
@@ -1,5 +1,4 @@
localCSS = require './style'
Ripple = require '../ripple'

module.exports = React.createClass

Expand All @@ -16,7 +15,6 @@ module.exports = React.createClass

getInitialState: ->
value : @props.value
ripple : undefined

# -- Lifecycle
componentWillReceiveProps: (next_props) ->
Expand All @@ -27,7 +25,6 @@ module.exports = React.createClass
unless @props.disabled
@setState
value : not @state.value
ripple: change: true
setTimeout (=> @props.onChange? event, @), 10

# -- Render
Expand All @@ -38,7 +35,6 @@ module.exports = React.createClass
<div data-react-toolbox='switch' className={className} onClick={@onClick}>
<span></span>
{ <label>{@props.label}</label> if @props.label }
<Ripple className={localCSS.ripple} origin={@state.ripple} />
</div>

# -- Extends
Expand Down
13 changes: 0 additions & 13 deletions components/switch/style.styl
@@ -1,16 +1,6 @@
@import '../constants'

SIZE = (SPACE / 1.25)
:local(.ripple)
z-index : -1
overflow : hidden
max-width : (SIZE * 2.7)
max-height : (SIZE * 2.7)
top : (SIZE / 2)
left : (SIZE * 2)
background-color : alpha(TEXT, 10%)
opacity : 0
animation-duration : (1.0 * ANIMATION_DURATION)

:local(.root)
position : relative
Expand Down Expand Up @@ -55,6 +45,3 @@ SIZE = (SPACE / 1.25)
background-color : PRIMARY
right : 0
box-shadow : ZDEPTH_SHADOW_2
> :local(.ripple)
left : 0
background-color : alpha(PRIMARY, 15%)

0 comments on commit 44cab7f

Please sign in to comment.