From 7796fb2677b547bec838eeaf4c219ffb00825c49 Mon Sep 17 00:00:00 2001 From: M03M Date: Mon, 20 Apr 2015 10:05:53 -0500 Subject: [PATCH 1/5] [Refactor] Moved merge function from theme-manager to its own file. Added new styling function and tested it with checkbox. --- src/checkbox.jsx | 104 +++++++++++++++++++---------------- src/drop-down-menu.jsx | 2 +- src/mixins/style-propable.js | 15 ++++- src/styles/theme-manager.js | 46 ++-------------- src/utils/extend.js | 34 ++++++++++++ 5 files changed, 112 insertions(+), 89 deletions(-) create mode 100644 src/utils/extend.js diff --git a/src/checkbox.jsx b/src/checkbox.jsx index 92bb19c44a505d..edd0936996e792 100644 --- a/src/checkbox.jsx +++ b/src/checkbox.jsx @@ -31,60 +31,72 @@ var Checkbox = React.createClass({ return this.context.theme.component.checkbox; }, + getStyles: function() { + var checkboxSize = 24; + var styles = { + icon: { + height: checkboxSize, + width: checkboxSize, + }, + check: { + positiion: 'absolute', + opacity: 0, + transform: 'scale(0)', + transitionOrigin: '50% 50%', + transition: Transitions.easeOut('450ms', 'opacity', '0ms') + ', ' + + Transitions.easeOut('0ms', 'transform', '450ms'), + fill: this.getTheme().checkedColor + }, + box: { + position: 'absolute', + opacity: 1, + fill: this.getTheme().boxColor, + transition: Transitions.easeOut('2s', null, '200ms') + }, + checkWhenSwitched: { + opacity: 1, + transform: 'scale(1)', + transition: Transitions.easeOut('0ms', 'opacity', '0ms') + ', ' + + Transitions.easeOut('800ms', 'transform', '0ms') + }, + boxWhenSwitched: { + transition: Transitions.easeOut('100ms', null, '0ms'), + fill: this.getTheme().checkedColor + }, + checkWhenDisabled: { + fill: this.getTheme().disabledColor + }, + boxWhenDisabled: { + fill: this.getTheme().disabledColor + } + }; + return styles; + }, + render: function() { var { onCheck, ...other } = this.props; - var checkboxSize = 24; - - var iconStyles = { - height: checkboxSize, - width: checkboxSize, - } - - var checkStyles = { - positiion: 'absolute', - opacity: 0, - transform: 'scale(0)', - transitionOrigin: '50% 50%', - transition: Transitions.easeOut('450ms', 'opacity', '0ms') + ', ' + - Transitions.easeOut('0ms', 'transform', '450ms'), - fill: this.getTheme().checkedColor - } - - var boxStyles = { - position: 'absolute', - opacity: 1, - fill: this.getTheme().boxColor, - transition: Transitions.easeOut('2s', null, '200ms') - } - - if (this.state.switched) { - checkStyles = this.mergeStyles(checkStyles, { - opacity: 1, - transform: 'scale(1)', - transition: Transitions.easeOut('0ms', 'opacity', '0ms') + ', ' + - Transitions.easeOut('800ms', 'transform', '0ms') - }); - boxStyles = this.mergeStyles(boxStyles, { - transition: Transitions.easeOut('100ms', null, '0ms'), - fill: this.getTheme().checkedColor - }); - } - - if (this.props.disabled) { - checkStyles.fill = this.getTheme().disabledColor; - boxStyles.fill = this.getTheme().disabledColor; - } - - if (this.state.switched && this.props.disabled) boxStyles.opacity = 0; + if (!this.hasOwnProperty('styles')) this.styles = this.getStyles(); var checkboxElement = (
- - + +
); @@ -93,7 +105,7 @@ var Checkbox = React.createClass({ inputType: "checkbox", switched: this.state.switched, switchElement: checkboxElement, - iconStyle: iconStyles, + iconStyle: this.styles.icon, onSwitch: this._handleCheck, onParentShouldUpdate: this._handleStateChange, defaultSwitched: this.props.defaultChecked, diff --git a/src/drop-down-menu.jsx b/src/drop-down-menu.jsx index 4f56c5335d160b..2869044b9ecaab 100644 --- a/src/drop-down-menu.jsx +++ b/src/drop-down-menu.jsx @@ -56,7 +56,7 @@ var DropDownMenu = React.createClass({ }, componentWillReceiveProps: function(nextProps) { - if (props.hasOwnProperty('selectedIndex')) { + if (nextProps.hasOwnProperty('selectedIndex')) { this._setSelectedIndex(nextProps); } }, diff --git a/src/mixins/style-propable.js b/src/mixins/style-propable.js index 0bf7202334246d..7c50529f1c6bac 100644 --- a/src/mixins/style-propable.js +++ b/src/mixins/style-propable.js @@ -1,5 +1,6 @@ var React = require('react/addons'); var AutoPrefix = require('../styles/auto-prefix'); +var Extend = require('../utils/extend'); /** * @params: @@ -16,6 +17,18 @@ module.exports = { mergeAndPrefix: function(styles, props) { return AutoPrefix.all(this.mergeStyles(styles, props)); - } + }, + /** + * m loops through all properties defined in the first argument, so overrides + * of undefined properties will not take place. + */ + m: function() { + var base = arguments[0]; + for (var i = 1; i < arguments.length; i++) { + if (arguments[i]) base = Extend(base, arguments[i]); + } + return AutoPrefix.all(base); + } + } diff --git a/src/styles/theme-manager.js b/src/styles/theme-manager.js index e0881153ac317c..dbddfaf90fec3b 100644 --- a/src/styles/theme-manager.js +++ b/src/styles/theme-manager.js @@ -1,6 +1,7 @@ var Color = require('./colors'); var Spacing = require('./spacing'); var ColorManipulator = require('../utils/color-manipulator'); +var Extend = require('../utils/extend'); var Types = { LIGHT: require('./themes/light-theme'), @@ -8,44 +9,6 @@ var Types = { }; var ThemeManager = function() { - - /** - * A recursive merge between two objects. Keep in mind that overriding the - * palette nested object of theme does not automatically update component - * properties, because they are still using the old color values of palette - * that they were defined with. - * - for all component variables of a theme. Use setPalette - * if you would like to override a theme's palette object. - * - * @param theme - the object whose properties are to be overwritten. It - * should be either the root level or some nested level - * of theme. - * @param overrides - an object containing properties to be overwritten. It - * should have the same structure as the theme object. - */ - var merge = function(theme, overrides) { - var mergeObject = {}; - - Object.keys(theme).forEach(function(currentKey) { - - var overridesCheck = theme[currentKey] && !Array.isArray(theme[currentKey]); - - // Recursive call to next level - if (typeof(theme[currentKey]) === 'object' && overridesCheck) - mergeObject[currentKey] = merge(theme[currentKey], overrides[currentKey]); - else { - if (overrides && overrides[currentKey]) - mergeObject[currentKey] = overrides[currentKey]; - else - mergeObject[currentKey] = theme[currentKey]; - } - - }); - - return mergeObject; - }; - return { types: Types, template: Types.LIGHT, @@ -60,18 +23,19 @@ var ThemeManager = function() { return this; }, + // Component gets updated to reflect palette changes. setTheme: function(newTheme) { this.setPalette(newTheme.getPalette()); this.setComponentThemes(newTheme.getComponentThemes(newTheme.getPalette())); }, setPalette: function(newPalette) { - this.palette = merge(this.palette, newPalette); - this.component = merge(this.component, this.template.getComponentThemes(this.palette)); + this.palette = Extend(this.palette, newPalette); + this.component = Extend(this.component, this.template.getComponentThemes(this.palette)); }, setComponentThemes: function(overrides) { - this.component = merge(this.component, overrides); + this.component = Extend(this.component, overrides); } }; }; diff --git a/src/utils/extend.js b/src/utils/extend.js new file mode 100644 index 00000000000000..14666d2351c477 --- /dev/null +++ b/src/utils/extend.js @@ -0,0 +1,34 @@ +/** +* A recursive merge between two objects. +* +* @param object - the object whose properties are to be overwritten. It +* should be either the root level or some nested level. +* @param overrides - an object containing properties to be overwritten. It +* should have the same structure as the object object. +*/ +var extend = function(object, overrides) { + var mergeObject = {}; + + Object.keys(object).forEach(function(currentKey) { + + var overridesCheck = object[currentKey] && !Array.isArray(object[currentKey]); + + // Recursive call to next level + if (typeof(object[currentKey]) === 'object' && overridesCheck) { + mergeObject[currentKey] = extend(object[currentKey], overrides[currentKey]); + } else { + if (overrides && overrides[currentKey]) { + mergeObject[currentKey] = overrides[currentKey]; + } else { + mergeObject[currentKey] = object[currentKey]; + } + } + + if (Object.keys(overrides) > 0) console.log('unadded props: ', overrides); + + }); + + return mergeObject; +}; + +module.exports = extend; \ No newline at end of file From 5365deb677d1c0a3d5174b6731983d445392caaa Mon Sep 17 00:00:00 2001 From: M03M Date: Tue, 21 Apr 2015 18:30:15 -0500 Subject: [PATCH 2/5] [Refactor] Created function m in StylePropable, and combined component style functions into a main style function called getStyles. --- .../components/code-example/code-example.jsx | 14 +- docs/src/app/components/pages/home.jsx | 20 +- docs/src/less/main.less | 3 - src/app-bar.jsx | 114 ++++--- src/before-after-wrapper.jsx | 4 +- src/checkbox.jsx | 16 +- src/date-picker/calendar.jsx | 2 +- src/date-picker/date-display.jsx | 2 +- src/dialog-window.jsx | 94 +++--- src/drop-down-icon.jsx | 59 ++-- src/drop-down-menu.jsx | 188 +++++------ src/enhanced-button.jsx | 51 +-- src/enhanced-switch.jsx | 116 ++++--- src/enhanced-textarea.jsx | 21 +- src/flat-button.jsx | 110 +++--- src/floating-action-button.jsx | 150 +++++---- src/font-icon.jsx | 34 +- src/icon-button.jsx | 118 +++---- src/ink-bar.jsx | 2 +- src/left-nav.jsx | 101 +++--- src/menu/link-menu-item.jsx | 57 ++-- src/menu/menu-item.jsx | 153 ++++----- src/menu/menu.jsx | 104 +++--- src/menu/subheader-menu-item.jsx | 69 ++-- src/mixins/style-propable.js | 3 +- src/overlay.jsx | 50 +-- src/paper.jsx | 63 ++-- src/radio-button.jsx | 97 +++--- src/raised-button.jsx | 145 ++++---- src/ripples/circle.jsx | 4 +- src/ripples/focus-ripple.jsx | 6 +- src/ripples/touch-ripple.jsx | 4 +- src/slider.jsx | 313 ++++++++---------- src/snackbar.jsx | 108 +++--- src/styles/themes/dark-theme.js | 2 +- src/styles/themes/light-theme.js | 2 +- src/svg-icons/svg-icon.jsx | 42 +-- src/tabs/tab.jsx | 4 +- src/tabs/tabs.jsx | 2 +- src/text-field.jsx | 235 ++++++------- src/toggle.jsx | 84 +++-- src/toolbar/toolbar-group.jsx | 4 +- src/toolbar/toolbar-separator.jsx | 4 +- src/toolbar/toolbar-title.jsx | 4 +- src/toolbar/toolbar.jsx | 8 +- src/tooltip.jsx | 132 ++++---- src/transition-groups/slide-in-child.jsx | 4 +- src/transition-groups/slide-in.jsx | 4 +- src/utils/extend.js | 19 +- 49 files changed, 1444 insertions(+), 1501 deletions(-) diff --git a/docs/src/app/components/code-example/code-example.jsx b/docs/src/app/components/code-example/code-example.jsx index 7475511b0d5a27..7f3690ecfd38a3 100644 --- a/docs/src/app/components/code-example/code-example.jsx +++ b/docs/src/app/components/code-example/code-example.jsx @@ -6,14 +6,22 @@ var React = require('react'), class CodeExample extends React.Component { render() { + var borderColor = this.context.theme.palette.borderColor; var style = { - color: this.context.theme.palette.textColor + label: { + color: borderColor + }, + block: { + borderRight: 'solid 1px ' + borderColor, + borderBottom: 'solid 1px ' + borderColor, + borderRadius: '0 0 2px 0' + } }; return ( -
example
-
+
example
+
{this.props.children}
{this.props.code} diff --git a/docs/src/app/components/pages/home.jsx b/docs/src/app/components/pages/home.jsx index 2f1b645fe0320e..2df9de0d9ece25 100644 --- a/docs/src/app/components/pages/home.jsx +++ b/docs/src/app/components/pages/home.jsx @@ -18,10 +18,10 @@ class HomePage extends React.Component { color: ThemeManager.palette.primary1Color, }, githubStyle: { - margin: '16px 32px 0px 8px', + margin: '16px 32px 0px 8px' }, demoStyle: { - margin: '16px 32px 0px 32px', + margin: '16px 32px 0px 32px' }, } } @@ -40,8 +40,20 @@ class HomePage extends React.Component { Components that Implement Google's Material Design - - + +
diff --git a/docs/src/less/main.less b/docs/src/less/main.less index ef6bf51f9a3c38..7e225314b0516f 100644 --- a/docs/src/less/main.less +++ b/docs/src/less/main.less @@ -91,10 +91,7 @@ body, h1, h2, h3, h4, h5, h6 { text-transform: uppercase; color: rgba(0, 0, 0, 0.26); // minBlack; padding: 8px; - border-right: solid 1px @border-color; - border-bottom: solid 1px @border-color; margin-bottom: 0; - border-radius: 0 0 2px 0; } .example-block, diff --git a/src/app-bar.jsx b/src/app-bar.jsx index c85f2038b8b3b6..76a00085894b25 100644 --- a/src/app-bar.jsx +++ b/src/app-bar.jsx @@ -32,52 +32,6 @@ var AppBar = React.createClass({ } }, - /** Styles */ - - _main: function() { - return this.mergeAndPrefix({ - zIndex: 5, - width: '100%', - minHeight: this.getSpacing().desktopKeylineIncrement, - backgroundColor: this.getThemeVariables().color, - }); - }, - - _title: function() { - return { - float: 'left', - paddingTop: 0, - letterSpacing: 0, - fontSize: '24px', - fontWeight: Typography.fontWeightNormal, - color: this.getThemeVariables().textColor, - lineHeight: this.getSpacing().desktopKeylineIncrement + 'px', - }; - }, - - _iconButton: function() { - var iconButtonSize = this.context.theme.component.button.iconButtonSize; - return { - style: { - marginTop: (this.getThemeVariables().height - iconButtonSize) / 2, - float: 'left', - marginRight: 8, - marginLeft: -16, - }, - iconStyle: { - fill: this.getThemeVariables().textColor, - color: this.getThemeVariables().textColor, - } - } - }, - - _paper: function() { - return { - paddingLeft: this.getSpacing().desktopGutter, - paddingRight: this.getSpacing().desktopGutter, - }; - }, - componentDidMount: function() { if (process.NODE_ENV !== 'production' && (this.props.iconElementLeft && this.props.iconClassNameLeft)) { @@ -95,40 +49,79 @@ var AppBar = React.createClass({ return this.context.theme.component.appBar; }, + getStyles: function(){ + var iconButtonSize = this.context.theme.component.button.iconButtonSize; + var styles = { + root: { + zIndex: 5, + width: '100%', + minHeight: this.getSpacing().desktopKeylineIncrement, + backgroundColor: this.getThemeVariables().color + }, + title: { + float: 'left', + paddingTop: 0, + letterSpacing: 0, + fontSize: '24px', + fontWeight: Typography.fontWeightNormal, + color: this.getThemeVariables().textColor, + lineHeight: this.getSpacing().desktopKeylineIncrement + 'px' + }, + iconButton: { + style: { + marginTop: (this.getThemeVariables().height - iconButtonSize) / 2, + float: 'left', + marginRight: 8, + marginLeft: -16 + }, + iconStyle: { + fill: this.getThemeVariables().textColor, + color: this.getThemeVariables().textColor + } + }, + paper: { + paddingLeft: this.getSpacing().desktopGutter, + paddingRight: this.getSpacing().desktopGutter + } + }; + return styles; + }, + render: function() { var { onTouchTap, ...other } = this.props; + var styles = this.getStyles(); var title, menuElementLeft, menuElementRight; - var iconRightStyle = this.mergeAndPrefix(this._iconButton().style, { + var iconRightStyle = this.m(styles.iconButton.style, { float: 'right', marginRight: -16, - marginLeft: 8, + marginLeft: 8 }); if (this.props.title) { // If the title is a string, wrap in an h1 tag. // If not, just use it as a node. title = Object.prototype.toString.call(this.props.title) === '[object String]' ? -

{this.props.title}

: +

{this.props.title}

: this.props.title; } if (this.props.showMenuIconButton) { if (this.props.iconElementLeft) { menuElementLeft = ( -
+
{this.props.iconElementLeft}
); } else { - var child = (this.props.iconClassNameLeft) ? '' : ; + var child = (this.props.iconClassNameLeft) ? '' : ; menuElementLeft = ( {child} @@ -146,7 +139,7 @@ var AppBar = React.createClass({ menuElementRight = ( @@ -155,10 +148,15 @@ var AppBar = React.createClass({ } return ( - - {menuElementLeft} - {title} - {menuElementRight} + + {menuElementLeft} + {title} + {menuElementRight} ); }, diff --git a/src/before-after-wrapper.jsx b/src/before-after-wrapper.jsx index b42963a588c55a..d04535fcb0efc5 100644 --- a/src/before-after-wrapper.jsx +++ b/src/before-after-wrapper.jsx @@ -74,11 +74,11 @@ var BeforeAfterWrapper = React.createClass({ if (this.props.beforeStyle) beforeElement = React.createElement( this.props.beforeElementType, - {style: this.mergeAndPrefix(beforeStyle, this.props.beforeStyle), + {style: this.m(beforeStyle, this.props.beforeStyle), key: "::before"} ); if (this.props.afterStyle) afterElement = React.createElement( this.props.afterElementType, - {style: this.mergeAndPrefix(afterStyle, this.props.afterStyle), + {style: this.m(afterStyle, this.props.afterStyle), key: "::after"} ); var children = [beforeElement, this.props.children, afterElement]; diff --git a/src/checkbox.jsx b/src/checkbox.jsx index edd0936996e792..75435dcd0984c3 100644 --- a/src/checkbox.jsx +++ b/src/checkbox.jsx @@ -79,23 +79,23 @@ var Checkbox = React.createClass({ ...other } = this.props; - if (!this.hasOwnProperty('styles')) this.styles = this.getStyles(); + var styles = this.getStyles(); var checkboxElement = (
); @@ -105,7 +105,7 @@ var Checkbox = React.createClass({ inputType: "checkbox", switched: this.state.switched, switchElement: checkboxElement, - iconStyle: this.styles.icon, + iconStyle: styles.icon, onSwitch: this._handleCheck, onParentShouldUpdate: this._handleStateChange, defaultSwitched: this.props.defaultChecked, diff --git a/src/date-picker/calendar.jsx b/src/date-picker/calendar.jsx index 2929cac86b03bf..d74b9c64d53837 100644 --- a/src/date-picker/calendar.jsx +++ b/src/date-picker/calendar.jsx @@ -94,7 +94,7 @@ var Calendar = React.createClass({ }; return ( - + +
+
{this.props.children} diff --git a/src/drop-down-icon.jsx b/src/drop-down-icon.jsx index 208e482cf7cdd4..f4f356e40cac93 100644 --- a/src/drop-down-icon.jsx +++ b/src/drop-down-icon.jsx @@ -37,41 +37,36 @@ var DropDownIcon = React.createClass({ this.setState({ open: false }); }, - /** Styles */ - - _main: function() { + getStyles: function() { var iconWidth = 48; - return this.mergeAndPrefix({ - display: 'inline-block', - width: iconWidth + 'px !important', - position: 'relative', - height: Spacing.desktopToolbarHeight, - fontSize: Spacing.desktopDropDownMenuFontSize, - cursor: 'pointer' - }); - }, - - _menu: function() { - - return { - transition: Transitions.easeOut(), - right: '-14px !important', - top: '9px !important', - opacity: (this.props.open) ? 1 : 0, - } - }, - - _menuItem: function() { // similair to drop down menu's menu item styles - return { - paddingRight: (Spacing.iconSize + (Spacing.desktopGutterLess*2)), - height: Spacing.desktopDropDownMenuItemHeight, - lineHeight: Spacing.desktopDropDownMenuItemHeight + 'px', - } + var styles = { + root: { + display: 'inline-block', + width: iconWidth + 'px !important', + position: 'relative', + height: Spacing.desktopToolbarHeight, + fontSize: Spacing.desktopDropDownMenuFontSize, + cursor: 'pointer' + }, + menu: { + transition: Transitions.easeOut(), + right: '-14px !important', + top: '9px !important', + opacity: (this.props.open) ? 1 : 0 + }, + menuItem: { // similair to drop down menu's menu item styles + paddingRight: (Spacing.iconSize + (Spacing.desktopGutterLess*2)), + height: Spacing.desktopDropDownMenuItemHeight, + lineHeight: Spacing.desktopDropDownMenuItemHeight + 'px' + } + }; + return styles; }, render: function() { + var styles = this.getStyles(); return ( -
+
diff --git a/src/drop-down-menu.jsx b/src/drop-down-menu.jsx index 2869044b9ecaab..fd86298c46330a 100644 --- a/src/drop-down-menu.jsx +++ b/src/drop-down-menu.jsx @@ -61,110 +61,6 @@ var DropDownMenu = React.createClass({ } }, - /** Styles */ - _main: function() { - var style = { - transition: Transitions.easeOut(), - position: 'relative', - display: 'inline-block', - height: this.getSpacing().desktopToolbarHeight, - fontSize: this.getSpacing().desktopDropDownMenuFontSize - }; - - if (this.state.open) style.opacity = 1; - - return this.mergeAndPrefix(style); - }, - - _control: function() { - var style = { - cursor: 'pointer', - position: 'static', - height: '100%', - }; - - if (this.props.styleControl) this.mergeAndPrefix(style, this.props.styleControl); - - return style; - }, - - _controlBg: function() { - var style = { - transition: Transitions.easeOut(), - backgroundColor: this.context.theme.component.menu.backgroundColor, - height: '100%', - width: '100%', - opacity: (this.state.open) ? 0 : - (this.state.isHovered) ? 1 : 0, - }; - - if (this.props.styleControlBg) style = this.mergeAndPrefix(style, this.props.styleControlBg); - - return style; - }, - - _icon: function() { - var style = { - position: 'absolute', - top: ((this.getSpacing().desktopToolbarHeight - 24) / 2), - right: this.getSpacing().desktopGutterLess, - fill: this.context.theme.component.dropDownMenu.accentColor, - }; - - if (this.props.styleIcon) style = this.mergeAndPrefix(style, this.props.styleIcon); - - return style; - }, - - _label: function() { - var style = { - transition: Transitions.easeOut(), - lineHeight: this.getSpacing().desktopToolbarHeight + 'px', - position: 'absolute', - paddingLeft: this.getSpacing().desktopGutter, - top: 0, - opacity: 1, - color: this.getTextColor() - }; - - if (this.state.open) { - style = this.mergeAndPrefix(style, { - opacity: 0, - top: this.getSpacing().desktopToolbarHeight / 2, - }); - } - - if (this.props.styleLabel) style = this.mergeAndPrefix(style, this.props.styleLabel); - - return style; - }, - - _underline: function() { - var style = { - borderTop: 'solid 1px ' + this.context.theme.component.dropDownMenu.accentColor, - margin: '0 ' + this.getSpacing().desktopGutter + 'px', - }; - - if (this.props.styleUnderline) style =this.mergeAndPrefix(style, this.props.styleUnderline); - - return style; - }, - - _menuItem: function() { - var style = { - paddingRight: this.getSpacing().iconSize + - this.getSpacing().desktopGutterLess + - this.getSpacing().desktopGutterMini, - height: this.getSpacing().desktopDropDownMenuItemHeight, - lineHeight: this.getSpacing().desktopDropDownMenuItemHeight + 'px', - whiteSpace: 'nowrap', - }; - - if (this.props.styleMenuItem) style = this.mergeAndPrefix(style, this.props.styleMenuItem); - - return style; - }, - getSpacing: function() { return this.context.theme.spacing; }, @@ -173,21 +69,85 @@ var DropDownMenu = React.createClass({ return this.context.theme.palette.textColor; }, + getStyles: function(){ + var styles = { + root: { + transition: Transitions.easeOut(), + position: 'relative', + display: 'inline-block', + height: this.getSpacing().desktopToolbarHeight, + fontSize: this.getSpacing().desktopDropDownMenuFontSize + }, + control: { + cursor: 'pointer', + position: 'static', + height: '100%' + }, + controlBg: { + transition: Transitions.easeOut(), + backgroundColor: this.context.theme.component.menu.backgroundColor, + height: '100%', + width: '100%', + opacity: (this.state.open) ? 0 : + (this.state.isHovered) ? 1 : 0 + }, + icon: { + position: 'absolute', + top: ((this.getSpacing().desktopToolbarHeight - 24) / 2), + right: this.getSpacing().desktopGutterLess, + fill: this.context.theme.component.dropDownMenu.accentColor + }, + label: { + transition: Transitions.easeOut(), + lineHeight: this.getSpacing().desktopToolbarHeight + 'px', + position: 'absolute', + paddingLeft: this.getSpacing().desktopGutter, + top: 0, + opacity: 1, + color: this.getTextColor() + }, + underline: { + borderTop: 'solid 1px ' + this.context.theme.component.dropDownMenu.accentColor, + margin: '0 ' + this.getSpacing().desktopGutter + 'px' + }, + menuItem: { + paddingRight: this.getSpacing().iconSize + + this.getSpacing().desktopGutterLess + + this.getSpacing().desktopGutterMini, + height: this.getSpacing().desktopDropDownMenuItemHeight, + lineHeight: this.getSpacing().desktopDropDownMenuItemHeight + 'px', + whiteSpace: 'nowrap' + }, + rootWhenOpen: { + opacity: 1 + }, + labelWhenOpen: { + opacity: 0, + top: this.getSpacing().desktopToolbarHeight / 2 + } + }; + return styles; + }, + render: function() { + var styles = this.getStyles(); return (
- - - -
+ onMouseOver={this._handleMouseOver} + className={this.props.className} + style={this.m( + styles.root, + this.state.open && styles.rootWhenOpen, + this.props.style)} > + + + +
{this.props.menuItems[this.state.selectedIndex].text}
- -
+ +
diff --git a/src/enhanced-button.jsx b/src/enhanced-button.jsx index 5995404d765f0e..368e060f913a71 100644 --- a/src/enhanced-button.jsx +++ b/src/enhanced-button.jsx @@ -57,33 +57,29 @@ var EnhancedButton = React.createClass({ } }, - /** Styles */ - _main: function() { - var style = { - border: 10, - background: 'none', - boxSizing: 'border-box', - font: 'inherit', - fontFamily: this.context.theme.contentFontFamily, - WebkitTapHighlightColor: 'rgba(0, 0, 0, 0)', - WebkitApperance: 'button' - }; - - if (this.props.linkButton) { - style = this.mergeAndPrefix({ + getStyles: function() { + var styles = { + root: { + border: 10, + background: 'none', + boxSizing: 'border-box', + font: 'inherit', + fontFamily: this.context.theme.contentFontFamily, + WebkitTapHighlightColor: 'rgba(0, 0, 0, 0)', + WebkitApperance: 'button' + }, + rootWhenLinkButton: { display: 'inline-block', cursor: (this.props.disabled) ? 'default' : 'pointer', - textDecoration: 'none', - }, style); - } - - if (this.props.disabled) style.cursor = 'default'; - - - return this.mergeAndPrefix(style); + textDecoration: 'none' + }, + rootWhenDisabled: { + cursor: 'default' + } + }; + return styles; }, - render: function() { var { centerRipple, @@ -98,6 +94,13 @@ var EnhancedButton = React.createClass({ onTouchTap, ...other } = this.props; + var styles = this.m( + this.getStyles().root, + this.props.linkButton && this.getStyles().rootWhenLinkButton, + this.props.disabled && this.getStyles().rootWhenDisabled, + this.props.style + ); + var touchRipple = ( ); var buttonProps = { - style: this._main(), + style: styles, disabled: disabled, onBlur: this._handleBlur, onFocus: this._handleFocus, diff --git a/src/enhanced-switch.jsx b/src/enhanced-switch.jsx index 28f71a188a4e13..f4cef0da302b49 100644 --- a/src/enhanced-switch.jsx +++ b/src/enhanced-switch.jsx @@ -46,20 +46,21 @@ var EnhancedSwitch = React.createClass({ getInitialState: function() { return { - isKeyboardFocused: false + isKeyboardFocused: false, + parentWidth: 100, }; }, getEvenWidth: function(){ return ( parseInt(window - .getComputedStyle(this.getDOMNode()) + .getComputedStyle(React.findDOMNode(this.refs.root)) .getPropertyValue('width'), 10) ); }, componentDidMount: function() { - var inputNode = this.refs.checkbox.getDOMNode(); + var inputNode = React.findDOMNode(this.refs.checkbox); if (!this.props.switched || this.props.switched == undefined || inputNode.checked != this.props.switched) this.props.onParentShouldUpdate(inputNode.checked); @@ -91,39 +92,19 @@ var EnhancedSwitch = React.createClass({ return this.context.theme.palette; }, - render: function() { - var { - type, - name, - value, - label, - onSwitch, - defaultSwitched, - onBlur, - onFocus, - onMouseUp, - onMouseDown, - onMouseOut, - onTouchStart, - onTouchEnd, - disableTouchRipple, - disableFocusRipple, - ...other - } = this.props; - + getStyles: function() { var switchWidth = 60 - Spacing.desktopGutterLess; var labelWidth = this.state.parentWidth - 60; - - var styles = this.mergeStyles({ + var styles = { + root: { position: 'relative', cursor: this.props.disabled ? 'default' : 'pointer', overflow: 'visible', display: 'table', height: 'auto', - width: '100%', - }); - - var inputStyles = { + width: '100%' + }, + input: { position: 'absolute', cursor: this.props.disabled ? 'default' : 'pointer', pointerEvents: 'all', @@ -133,10 +114,17 @@ var EnhancedSwitch = React.createClass({ zIndex: 2, left: 0, boxSizing: 'border-box', - padding: 0, - }; - - var wrapStyles = this.mergeStyles({ + padding: 0 + }, + label: { + float: 'left', + position: 'relative', + display: 'table-column', + width: labelWidth, + lineHeight: '24px', + color: this.getTheme().textColor + }, + wrap: { transition: Transitions.easeOut(), float: 'left', position: 'relative', @@ -146,16 +134,43 @@ var EnhancedSwitch = React.createClass({ Spacing.desktopGutterLess : 0, marginLeft: (this.props.labelPosition == 'left') ? Spacing.desktopGutterLess : 0 - }, this.props.iconStyle); + }, + ripple: { + height: '200%', + width: '200%', + top: '-12', + left: '-12' + } + }; + return styles; + }, - var labelStyles = { - float: 'left', - position: 'relative', - display: 'table-column', - width: labelWidth, - lineHeight: '24px', - color: this.getTheme().textColor - } + render: function() { + var { + type, + name, + value, + label, + onSwitch, + defaultSwitched, + onBlur, + onFocus, + onMouseUp, + onMouseDown, + onMouseOut, + onTouchStart, + onTouchEnd, + disableTouchRipple, + disableFocusRipple, + ...other + } = this.props; + + var styles = this.getStyles(); + + styles.root.cursor = styles.root.input = this.props.disabled ? 'default' : 'pointer'; + + var wrapStyles = this.m(styles.wrap, this.props.iconStyle); + var rippleStyle = this.m(styles.ripple, this.props.rippleStyle); if (this.props.thumbStyle) { wrapStyles.marginLeft /= 2; @@ -165,7 +180,7 @@ var EnhancedSwitch = React.createClass({ var inputId = this.props.id || UniqueId.generate(); var labelElement = this.props.label ? ( -