Rewrite button in ES6 and refactor the ripple effect on it

old
Javi Velasco 2015-09-18 21:03:08 +02:00
parent 44cab7f311
commit cac6eed1ea
8 changed files with 96 additions and 131 deletions

View File

@ -2,28 +2,24 @@
```
var Button = require('react-toolbox/components/button');
<Button caption="Login" />
<Button caption="Primary" className="primary" icon="access_alarm" />
<Button caption="Secondary" className="accent" />
<Button caption="Disabled" disabled />
<Button type="circle" icon="access_alarm" />
<Button type="circle" icon="explore" className="primary" />
<Button type="circle" icon="zoom_in" className="accent" />
<Button type="circle" icon="input" disabled={true} />
<Button className="accent" label="Flat button" />
<Button className="primary" type="raised" label="Raised" />
<Button className="accent" type="raised" label="Raised" icon="assignment_turned_in" />
<Button className="primary" type="floating" icon="add" />
<Button className="accent mini" type="floating" icon="add" />
```
## Properties
| Name | Type | Default | Description|
|:- |:-: | :- |:-|
| **caption** | String | | The text string to use for the floating label element.|
| **className** | String | | Set the class-styles of the Component.|
| **disabled** | Boolean | | If true, component will be disabled.|
| **icon** | String | | Default value using JSON data.|
| **label** | String | | The text string to use for the floating label element.|
| **loading** | Boolean | | If true, component will be disabled and show a loading animation.|
| **type** | String | "text" | Type of the component, overwrite this property if you need set a different stylesheet.|
| **ripple** | Boolean | | If true, component will have a ripple effect on click.|
| **type** | String | "flat" | Type of the component, overwrite this property if you need set a different stylesheet.|
## Methods

View File

@ -1,61 +0,0 @@
localCSS = require './style'
FontIcon = require '../font_icon'
Ripple = require '../ripple'
module.exports = React.createClass
displayName : 'Button'
# -- States & Properties
propTypes:
caption : React.PropTypes.string
className : React.PropTypes.string
disabled : React.PropTypes.bool
icon : React.PropTypes.string
loading : React.PropTypes.bool
type : React.PropTypes.string
getDefaultProps: ->
className : ''
type : 'raised'
getInitialState: ->
loading : @props.loading
focused : false
ripple : undefined
# -- Lifecycle
componentWillReceiveProps: ->
@setState ripple: undefined
# -- Events
onClick: (event) ->
event.preventDefault()
client = event.target.getBoundingClientRect?()
@setState
focused: true
ripple:
left : event.pageX - client?.left
top : event.pageY - client?.top
width : (client?.width * 2.5)
@props.onClick? event, @
setTimeout (=> @setState focused: false), 450
# -- Render
render: ->
className = @props.className
className += " #{@props.type}" if @props.type
className += ' focused' if @state.focused
<button data-react-toolbox='button'
onClick={@onClick}
className={localCSS.root + ' ' + className}
disabled={@props.disabled or @state.loading}
data-flex='horizontal center'>
{ <FontIcon value={@props.icon} /> if @props.icon }
{ <abbr>{@props.caption}</abbr> if @props.caption }
<Ripple origin={@state.ripple} loading={@state.loading} />
</button>
# -- Extends
loading: (value) ->
@setState loading: value

View File

@ -0,0 +1,62 @@
/* global React */
import { addons } from 'react/addons';
import css from './style';
import FontIcon from '../font_icon';
import Ripple from '../ripple';
export default React.createClass({
mixins: [addons.PureRenderMixin],
displayName: 'Button',
propTypes: {
className: React.PropTypes.string,
disabled: React.PropTypes.bool,
icon: React.PropTypes.string,
label: React.PropTypes.string,
loading: React.PropTypes.bool,
ripple: React.PropTypes.bool,
type: React.PropTypes.string
},
getDefaultProps () {
return {
className: '',
ripple: true,
type: 'flat'
};
},
getInitialState () {
return { loading: this.props.loading };
},
handleClick (event) {
if (this.props.onClick) this.props.onClick(event, this);
},
render () {
let className = this.props.className;
if (this.props.type) className += ` ${this.props.type}`;
if (this.state.focused) className += ' focused';
return (
<button
className={css.root + ' ' + className}
data-flex='horizontal center'
data-react-toolbox='button'
disabled={this.props.disabled || this.state.loading}
onClick={this.handleClick}
>
{ this.props.icon ? <FontIcon value={this.props.icon}/> : null }
{ this.props.label ? <abbr>{this.props.label}</abbr> : null }
{ this.props.ripple ? <Ripple loading={this.props.loading}/> : null }
</button>
);
},
loading (value) {
this.setState({loading: value});
}
});

View File

@ -51,10 +51,17 @@
> [data-react-toolbox='icon']
line-height : BUTTON_CIRCLE_HEIGHT
&.mini
width : BUTTON_CIRCLE_MINI_HEIGHT
height : BUTTON_CIRCLE_MINI_HEIGHT
> [data-react-toolbox='icon']
line-height : BUTTON_CIRCLE_MINI_HEIGHT
// Overrides
&[disabled]
color : darken(DIVIDER, 25%)
background-color : DIVIDER
pointer-events : none
&:not([disabled])
cursor : pointer
@ -65,7 +72,7 @@
&:not(.primary):not(.accent)
color : TEXT
background-color : WHITE
&.focused
&:active
box-shadow : ZDEPTH_SHADOW_2, inset 0 0 0 UNIT alpha(WHITE, 10%)
&.primary, &.accent
color : WHITE
@ -76,6 +83,3 @@
&:not(.primary):not(.accent) > [data-react-toolbox='ripple']
background-color : DIVIDER
> *
pointer-events: none

View File

@ -36,6 +36,7 @@ HEADER_HEIGHT = (1.65 * UNIT)
INPUT_HEIGHT = (2 * SPACE)
BUTTON_HEIGHT = (2.5 * SPACE)
BUTTON_CIRCLE_HEIGHT = (2.75 * SPACE)
BUTTON_CIRCLE_MINI_HEIGHT = (2 * SPACE)
LOADING_HEIGHT = (1.5 * UNIT)
PROGRESS_BAR_HEIGHT = (SPACE / 4)

View File

@ -1,37 +0,0 @@
localCSS = require './style'
module.exports = React.createClass
# -- States & Properties
propTypes:
className : React.PropTypes.string
loading : React.PropTypes.bool
origin : React.PropTypes.object
getDefaultProps: ->
className : ''
loading : false
getInitialState: ->
className : undefined
# -- Lifecycle
componentWillReceiveProps: (next_props) ->
@setState className: "active" if next_props.origin?
componentDidMount: ->
el = @getDOMNode()
for key in ['animationend', 'webkitAnimationEnd', 'oAnimationEnd', 'MSAnimationEnd']
el.addEventListener key, (=> @setState className: undefined), false
@setState className: 'active' if @props.origin?
# -- Render
render: ->
className = "#{localCSS.root} #{@props.className} #{@state.className}"
className += ' loading' if @props.loading
<div data-react-toolbox='ripple' className={className}
style={
left : @props.origin?.left,
top : @props.origin?.top,
width : @props.origin?.width,
height: @props.origin?.width} />

View File

@ -15,21 +15,9 @@ module.exports = React.createClass
<section>
<h2>Buttons</h2>
<p>lorem ipsum...</p>
<Button caption="Login"/>
<Button caption="Login" type="flat" />
<Button caption="Primary" className="primary" icon="access_alarm" type="flat" />
<Button caption="Secondary" className="accent" type="flat" />
<Button caption="Disabled" disabled type="flat" />
<Button caption="Primary" className="primary" icon="access_alarm" />
<Button caption="Secondary" className="accent" />
<Button caption="Disabled" disabled />
<Button caption="loading" loading />
<Button type="floating" icon="access_alarm" />
<Button type="floating" icon="explore" className="primary" />
<Button type="floating" icon="zoom_in" className="accent" />
<Button type="floating" icon="input" disabled />
<Button type="floating" icon="zoom_in" loading />
<Button className="accent" label="Flat button" />
<Button className="primary" type="raised" label="Raised" />
<Button className="accent" type="raised" label="Raised" icon="assignment_turned_in" />
<Button className="primary" type="floating" icon="add" />
<Button className="accent mini" type="floating" icon="add" />
</section>

View File

@ -25,7 +25,19 @@ Test = React.createClass
render: ->
<app data-toolbox={true}>
<h1>React-Toolbox <small>New way for create</small></h1>
<Aside />
<Autocomplete />
<Button />
<Card />
<Dialog />
<Dropdown />
<FontIcon />
<Form />
<Progress />
<Slider />
<Switch />
<Tabs />
<Pickers />
</app>
React.render <Test/>, document.body