A Pen by Ken Wheeler on CodePen.
Created
January 30, 2015 18:04
-
-
Save shawnsandy/3a4eb3ee53f0957d6a81 to your computer and use it in GitHub Desktop.
Material Design Button in ReactJS with Encapsulated Styles
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <div id="container"></div> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * Material Design Button with Encapsulated Styling | |
| * By: Ken Wheeler (http://kenwheeler.github.io) | |
| * Based on slides/theory by Vjeux, and with a little help from him as well :) | |
| * Slides from the original presentation available at: https://speakerdeck.com/vjeux/react-css-in-js | |
| */ | |
| // Define Material Button Class | |
| var MaterialButton = React.createClass({ | |
| // Set initial state | |
| getInitialState: function(){ | |
| return { style: 'default' }; | |
| }, | |
| // Handle click event | |
| onClick: function(){ | |
| // Fire click event if supplies via props | |
| this.props.onClick && this.props.onClick(); | |
| // Make ripple transition relative to click position | |
| _.extend(styles.rippleActive, { | |
| transformOrigin: event.offsetX + "px " + event.offsetY + "px" | |
| }); | |
| // Set active state | |
| this.setState({style: 'active'}); | |
| // In 100ms, set out state | |
| setTimeout(function(){ | |
| this.setState({style: 'out'}); | |
| // In another 100ms, return to default state | |
| setTimeout(function(){ | |
| this.setState({style: 'default'}); | |
| }.bind(this), 200); | |
| }.bind(this), 200); | |
| }, | |
| // Handle mouse down | |
| onMouseDown: function() { | |
| // Set pressed state | |
| this.setState({style: 'pressed'}); | |
| }, | |
| // Render component | |
| render: function() { | |
| // Set state to this.state.style | |
| var state = this.state.style; | |
| // Set button style based off of state to style in styles object | |
| var buttonStyle = _.extend({}, | |
| styles.button, | |
| state === 'pressed' && styles.pressed | |
| ); | |
| // Set ripple style based off of state to style in styles object | |
| var rippleStyle = _.extend({}, | |
| styles.ripple, | |
| state === 'active' && styles.rippleActive, | |
| state === 'out' && styles.rippleOut | |
| ); | |
| // Return component | |
| return ( | |
| <button style={buttonStyle} | |
| onMouseDown={this.onMouseDown} | |
| onTouchStart={this.onMouseDown} | |
| onClick={this.onClick} | |
| type="button"> | |
| + | |
| <span style={rippleStyle}></span> | |
| </button> | |
| ); | |
| } | |
| }); | |
| // Define styles object to be applied conditionally via state changes | |
| var styles = { | |
| button: { | |
| position: 'relative', | |
| border: 'none', | |
| outline: 'none', | |
| color: 'white', | |
| borderRadius: 56, | |
| boxShadow: '0 3px 10px rgba(0, 0, 0, 0.23)', | |
| backgroundColor: '#d23f31', | |
| fontSize: 18, | |
| height: 56, | |
| width: 56, | |
| WebkitTapHighlightColor: 'rgba(0,0,0,0)', | |
| transition: '200ms all ease', | |
| userSelect: 'none', | |
| WebkitUserSelect: 'none', | |
| WebkitTransition: '200ms all ease' | |
| }, | |
| pressed: { | |
| backgroundColor: '#ab3125', | |
| boxShadow: '0 8px 17px 0 rgba(0, 0, 0, 0.1)' | |
| }, | |
| ripple: { | |
| position: 'absolute', | |
| top: 0, | |
| left: 0, | |
| height: '100%', | |
| width: '100%', | |
| borderRadius: '100%', | |
| display: 'block', | |
| background: 'rgba(255,255,255,0.2)', | |
| transform: 'scale(0)', | |
| webkitTransform: 'scale(0)' | |
| }, | |
| rippleActive: { | |
| transform: 'scale(1)', | |
| webkitTransform: 'scale(1)', | |
| transition: '200ms all ease', | |
| webkitTransition: '200ms all ease' | |
| }, | |
| rippleOut: { | |
| opacity: 0, | |
| } | |
| }; | |
| // Render component | |
| React.render(<MaterialButton />, document.getElementById('container')); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #container { | |
| position: absolute; | |
| top: 50%; | |
| left: 50%; | |
| transform: translate(-50%, -50%); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment