From 50a74a93ff7592280002540acb22d3e8e92a38e8 Mon Sep 17 00:00:00 2001 From: Peter Fern Date: Sat, 23 Jan 2016 14:19:40 +1100 Subject: [PATCH] Fix a few unthemable elements Adjust textColor or canvasColor to find suitable replacements for hard-coded blacks/whites/greys Conflicts: src/ripples/focus-ripple.jsx --- src/avatar.jsx | 13 ++++++------- src/card/card-header.jsx | 8 ++++---- src/card/card-title.jsx | 13 +++---------- src/floating-action-button.jsx | 2 -- src/lists/list.jsx | 4 +++- src/ripples/circle-ripple.jsx | 2 -- src/ripples/focus-ripple.jsx | 33 +++++++++++++++++++++++++++++---- src/ripples/touch-ripple.jsx | 22 +++++++++++++++++++++- src/styles/getMuiTheme.js | 29 ++++++++++++++++++++++++----- src/toolbar/toolbar-group.jsx | 34 ++++++++++++++-------------------- src/utils/color-manipulator.js | 12 ++++++------ 11 files changed, 110 insertions(+), 62 deletions(-) diff --git a/src/avatar.jsx b/src/avatar.jsx index 42a00d6423ee1f..f9f994ea36c92a 100644 --- a/src/avatar.jsx +++ b/src/avatar.jsx @@ -1,6 +1,5 @@ import React from 'react'; import StylePropable from './mixins/style-propable'; -import Colors from './styles/colors'; import DefaultRawTheme from './styles/raw-themes/light-raw-theme'; import ThemeManager from './styles/theme-manager'; @@ -61,8 +60,6 @@ const Avatar = React.createClass({ getDefaultProps() { return { - backgroundColor: Colors.grey400, - color: Colors.white, size: 40, }; }, @@ -87,6 +84,8 @@ const Avatar = React.createClass({ }, render() { + const theme = this.state.muiTheme.avatar; + let { backgroundColor, color, @@ -109,7 +108,7 @@ const Avatar = React.createClass({ }; if (src) { - const borderColor = this.state.muiTheme.avatar.borderColor; + const borderColor = theme.borderColor; if (borderColor) { styles.root = this.mergeStyles(styles.root, { @@ -129,11 +128,11 @@ const Avatar = React.createClass({ ); } else { styles.root = this.mergeStyles(styles.root, { - backgroundColor: backgroundColor, + backgroundColor: backgroundColor || theme.backgroundColor, textAlign: 'center', lineHeight: size + 'px', fontSize: size / 2 + 4, - color: color, + color: color || theme.color, }); const styleIcon = { @@ -141,7 +140,7 @@ const Avatar = React.createClass({ }; const iconElement = icon ? React.cloneElement(icon, { - color: color, + color: color || theme.color, style: this.mergeStyles(styleIcon, icon.props.style), }) : null; diff --git a/src/card/card-header.jsx b/src/card/card-header.jsx index a0891c55146886..28b005b8acda5e 100644 --- a/src/card/card-header.jsx +++ b/src/card/card-header.jsx @@ -42,8 +42,6 @@ const CardHeader = React.createClass({ getDefaultProps() { return { - titleColor: Styles.Colors.darkBlack, - subtitleColor: Styles.Colors.lightBlack, avatar: null, }; }, @@ -68,6 +66,8 @@ const CardHeader = React.createClass({ }, getStyles() { + const theme = this.state.muiTheme.card; + return { root: { height: 72, @@ -84,12 +84,12 @@ const CardHeader = React.createClass({ marginRight: 16, }, title: { - color: this.props.titleColor, + color: this.props.titleColor || theme.titleColor, display: 'block', fontSize: 15, }, subtitle: { - color: this.props.subtitleColor, + color: this.props.subtitleColor || theme.subtitleColor, display: 'block', fontSize: 14, }, diff --git a/src/card/card-title.jsx b/src/card/card-title.jsx index 4f202a850867b5..6595761f54e315 100644 --- a/src/card/card-title.jsx +++ b/src/card/card-title.jsx @@ -1,5 +1,4 @@ import React from 'react'; -import Styles from '../styles'; import StylePropable from '../mixins/style-propable'; import ThemeManager from '../styles/theme-manager'; import DefaultRawTheme from '../styles/raw-themes/light-raw-theme'; @@ -37,13 +36,6 @@ const CardTitle = React.createClass({ StylePropable, ], - getDefaultProps() { - return { - titleColor: Styles.Colors.darkBlack, - subtitleColor: Styles.Colors.lightBlack, - }; - }, - getInitialState() { return { muiTheme: this.context.muiTheme ? this.context.muiTheme : ThemeManager.getMuiTheme(DefaultRawTheme), @@ -66,6 +58,7 @@ const CardTitle = React.createClass({ }, getStyles() { + const theme = this.state.muiTheme.card; return { root: { padding: 16, @@ -73,13 +66,13 @@ const CardTitle = React.createClass({ }, title: { fontSize: 24, - color: this.props.titleColor, + color: this.props.titleColor || theme.titleColor, display: 'block', lineHeight: '36px', }, subtitle: { fontSize: 14, - color: this.props.subtitleColor, + color: this.props.subtitleColor || theme.subtitleColor, display: 'block', }, }; diff --git a/src/floating-action-button.jsx b/src/floating-action-button.jsx index e80940e9756356..4f4cf79bdf1d21 100644 --- a/src/floating-action-button.jsx +++ b/src/floating-action-button.jsx @@ -2,7 +2,6 @@ import React from 'react'; import ReactDOM from 'react-dom'; import StylePropable from './mixins/style-propable'; import Transitions from './styles/transitions'; -import Colors from './styles/colors'; import ColorManipulator from './utils/color-manipulator'; import EnhancedButton from './enhanced-button'; import FontIcon from './font-icon'; @@ -123,7 +122,6 @@ const FloatingActionButton = React.createClass({ getDefaultProps() { return { disabled: false, - disabledColor: Colors.grey300, mini: false, secondary: false, }; diff --git a/src/lists/list.jsx b/src/lists/list.jsx index 2173c801209269..af6578f3a35cad 100644 --- a/src/lists/list.jsx +++ b/src/lists/list.jsx @@ -83,6 +83,8 @@ const List = React.createClass({ }, render() { + const theme = this.state.muiTheme.list; + const { children, insetSubheader, @@ -101,7 +103,7 @@ const List = React.createClass({ }, subheader: { - color: Typography.textLightBlack, + color: theme.subheaderTextColor, fontSize: 14, fontWeight: Typography.fontWeightMedium, lineHeight: '48px', diff --git a/src/ripples/circle-ripple.jsx b/src/ripples/circle-ripple.jsx index ac770720a3e766..c932bfadfb9599 100644 --- a/src/ripples/circle-ripple.jsx +++ b/src/ripples/circle-ripple.jsx @@ -4,7 +4,6 @@ import PureRenderMixin from 'react-addons-pure-render-mixin'; import StylePropable from '../mixins/style-propable'; import autoPrefix from '../styles/auto-prefix'; import Transitions from '../styles/transitions'; -import Colors from '../styles/colors'; const CircleRipple = React.createClass({ @@ -31,7 +30,6 @@ const CircleRipple = React.createClass({ getDefaultProps() { return { - color: Colors.darkBlack, opacity: 0.16, }; }, diff --git a/src/ripples/focus-ripple.jsx b/src/ripples/focus-ripple.jsx index 65989eec0965ad..f747d02de314cb 100644 --- a/src/ripples/focus-ripple.jsx +++ b/src/ripples/focus-ripple.jsx @@ -3,9 +3,10 @@ import ReactDOM from 'react-dom'; import PureRenderMixin from 'react-addons-pure-render-mixin'; import StylePropable from '../mixins/style-propable'; import autoPrefix from '../styles/auto-prefix'; -import Colors from '../styles/colors'; import Transitions from '../styles/transitions'; import ScaleInTransitionGroup from '../transition-groups/scale-in'; +import ThemeManager from '../styles/theme-manager.js'; +import DefaultRawTheme from '../styles/raw-themes/light-raw-theme'; const pulsateDuration = 750; @@ -29,14 +30,29 @@ const FocusRipple = React.createClass({ style: React.PropTypes.object, }, + contextTypes: { + muiTheme: React.PropTypes.object, + }, + + //for passing default theme context to children + childContextTypes: { + muiTheme: React.PropTypes.object, + }, + mixins: [ PureRenderMixin, StylePropable, ], - getDefaultProps() { + getInitialState() { return { - color: Colors.darkBlack, + muiTheme: this.context.muiTheme ? this.context.muiTheme : ThemeManager.getMuiTheme(DefaultRawTheme), + }; + }, + + getChildContext() { + return { + muiTheme: this.state.muiTheme, }; }, @@ -47,6 +63,13 @@ const FocusRipple = React.createClass({ } }, + //to update theme inside state whenever a new theme is passed down + //from the parent / owner using context + componentWillReceiveProps(nextProps, nextContext) { + const newMuiTheme = nextContext.muiTheme ? nextContext.muiTheme : this.state.muiTheme; + this.setState({muiTheme: newMuiTheme}); + }, + componentDidUpdate() { if (this.props.show) { this._setRippleSize(); @@ -57,6 +80,8 @@ const FocusRipple = React.createClass({ }, _getRippleElement(props) { + const theme = this.state.muiTheme.ripple; + const { color, innerStyle, @@ -69,7 +94,7 @@ const FocusRipple = React.createClass({ width: '100%', borderRadius: '50%', opacity: opacity ? opacity : 0.16, - backgroundColor: color, + backgroundColor: color || theme.color, transition: Transitions.easeOut(pulsateDuration + 'ms', 'transform', null, Transitions.easeInOutFunction), }, innerStyle); diff --git a/src/ripples/touch-ripple.jsx b/src/ripples/touch-ripple.jsx index 449c9474ca3a36..b8138490d44383 100644 --- a/src/ripples/touch-ripple.jsx +++ b/src/ripples/touch-ripple.jsx @@ -5,6 +5,8 @@ import ReactTransitionGroup from 'react-addons-transition-group'; import StylePropable from '../mixins/style-propable'; import Dom from '../utils/dom'; import CircleRipple from './circle-ripple'; +import ThemeManager from '../styles/theme-manager.js'; +import DefaultRawTheme from '../styles/raw-themes/light-raw-theme'; import update from 'react-addons-update'; function push(array, obj) { @@ -36,6 +38,15 @@ const TouchRipple = React.createClass({ style: React.PropTypes.object, }, + contextTypes: { + muiTheme: React.PropTypes.object, + }, + + //for passing default theme context to children + childContextTypes: { + muiTheme: React.PropTypes.object, + }, + mixins: [ PureRenderMixin, StylePropable, @@ -55,10 +66,19 @@ const TouchRipple = React.createClass({ hasRipples: false, nextKey: 0, ripples: [], + muiTheme: this.context.muiTheme ? this.context.muiTheme : ThemeManager.getMuiTheme(DefaultRawTheme), + }; + }, + + getChildContext() { + return { + muiTheme: this.state.muiTheme, }; }, start(e, isRippleTouchGenerated) { + const theme = this.state.muiTheme.ripple; + if (this._ignoreNextMouseDown && !isRippleTouchGenerated) { this._ignoreNextMouseDown = false; return; @@ -72,7 +92,7 @@ const TouchRipple = React.createClass({ key={this.state.nextKey} muiTheme={this.props.muiTheme} style={!this.props.centerRipple ? this._getRippleStyle(e) : {}} - color={this.props.color} + color={this.props.color || theme.color} opacity={this.props.opacity} touchGenerated={isRippleTouchGenerated} /> diff --git a/src/styles/getMuiTheme.js b/src/styles/getMuiTheme.js index bc2464543476bc..12b1493fbbbadd 100644 --- a/src/styles/getMuiTheme.js +++ b/src/styles/getMuiTheme.js @@ -30,7 +30,11 @@ export default function getMuiTheme(baseTheme, muiTheme) { height: spacing.desktopKeylineIncrement, }, avatar: { - borderColor: 'rgba(0, 0, 0, 0.08)', + color: palette.canvasColor, + backgroundColor: ColorManipulator.luminance(palette.canvasColor) > 0.5 ? + ColorManipulator.darken(palette.canvasColor, 0.26) : + ColorManipulator.lighten(palette.canvasColor, 1.26, 1.0), + borderColor: ColorManipulator.fade(palette.textColor, 0.08), }, badge: { color: palette.alternateTextColor, @@ -45,6 +49,10 @@ export default function getMuiTheme(baseTheme, muiTheme) { minWidth: 88, iconButtonSize: spacing.iconSize * 2, }, + card: { + titleColor: ColorManipulator.fade(palette.textColor, 0.87), + subtitleColor: ColorManipulator.fade(palette.textColor, 0.54), + }, cardText: { textColor: palette.textColor, }, @@ -82,6 +90,9 @@ export default function getMuiTheme(baseTheme, muiTheme) { secondaryColor: palette.primary1Color, secondaryIconColor: palette.alternateTextColor, disabledTextColor: palette.disabledColor, + disabledColor: ColorManipulator.luminance(palette.canvasColor) > 0.5 ? + ColorManipulator.darken(palette.canvasColor, 0.12) : + ColorManipulator.lighten(palette.canvasColor, 1.12, 1.0), }, gridTile: { textColor: Colors.white, @@ -93,6 +104,9 @@ export default function getMuiTheme(baseTheme, muiTheme) { width: spacing.desktopKeylineIncrement * 4, color: palette.canvasColor, }, + list: { + subheaderTextColor: ColorManipulator.fade(palette.textColor, 0.54), + }, listItem: { nestedLevelDepth: 18, }, @@ -103,7 +117,7 @@ export default function getMuiTheme(baseTheme, muiTheme) { menuItem: { dataHeight: 32, height: 48, - hoverColor: 'rgba(0, 0, 0, .035)', + hoverColor: ColorManipulator.fade(palette.textColor, 0.035), padding: spacing.desktopGutter, selectedTextColor: palette.accent1Color, }, @@ -139,6 +153,9 @@ export default function getMuiTheme(baseTheme, muiTheme) { strokeColor: palette.borderColor, loadingStrokeColor: palette.primary1Color, }, + ripple: { + color: ColorManipulator.fade(palette.textColor, 0.87), + }, slider: { trackSize: 2, trackColor: palette.primary3Color, @@ -206,12 +223,14 @@ export default function getMuiTheme(baseTheme, muiTheme) { trackRequiredColor: ColorManipulator.fade(palette.primary1Color, 0.5), }, toolbar: { + color: ColorManipulator.fade(palette.textColor, 0.54), + hoverColor: ColorManipulator.fade(palette.textColor, 0.87), backgroundColor: ColorManipulator.darken(palette.accent2Color, 0.05), height: 56, titleFontSize: 20, - iconColor: 'rgba(0, 0, 0, .40)', - separatorColor: 'rgba(0, 0, 0, .175)', - menuHoverColor: 'rgba(0, 0, 0, .10)', + iconColor: ColorManipulator.fade(palette.textColor, 0.4), + separatorColor: ColorManipulator.fade(palette.textColor, 0.175), + menuHoverColor: ColorManipulator.fade(palette.textColor, 0.1), }, tabs: { backgroundColor: palette.primary1Color, diff --git a/src/toolbar/toolbar-group.jsx b/src/toolbar/toolbar-group.jsx index 35e17240940120..1c2e8c3baeb581 100644 --- a/src/toolbar/toolbar-group.jsx +++ b/src/toolbar/toolbar-group.jsx @@ -1,5 +1,4 @@ import React from 'react'; -import Colors from '../styles/colors'; import StylePropable from '../mixins/style-propable'; import DefaultRawTheme from '../styles/raw-themes/light-raw-theme'; import ThemeManager from '../styles/theme-manager'; @@ -77,23 +76,18 @@ const ToolbarGroup = React.createClass({ this.setState({muiTheme: newMuiTheme}); }, - getTheme() { - return this.state.muiTheme.toolbar; - }, - - getSpacing() { - return this.state.muiTheme.rawTheme.spacing; - }, - getStyles() { + const theme = this.state.muiTheme.toolbar; + const spacing = this.state.muiTheme.rawTheme.spacing; + const { firstChild, float, lastChild, } = this.props; - const marginHorizontal = this.getSpacing().desktopGutter; - const marginVertical = (this.getTheme().height - this.state.muiTheme.button.height) / 2; + const marginHorizontal = spacing.desktopGutter; + const marginVertical = (theme.height - this.state.muiTheme.button.height) / 2; const styles = { root: { float, @@ -104,12 +98,12 @@ const ToolbarGroup = React.createClass({ dropDownMenu: { root: { float: 'left', - color: Colors.lightBlack, // removes hover color change, we want to keep it + color: theme.color, // removes hover color change, we want to keep it display: 'inline-block', - marginRight: this.getSpacing().desktopGutter, + marginRight: spacing.desktopGutter, }, controlBg: { - backgroundColor: this.getTheme().menuHoverColor, + backgroundColor: theme.menuHoverColor, borderRadius: 0, }, underline: { @@ -125,18 +119,18 @@ const ToolbarGroup = React.createClass({ root: { float: 'left', cursor: 'pointer', - color: this.getTheme().iconColor, - lineHeight: this.getTheme().height + 'px', - paddingLeft: this.getSpacing().desktopGutter, + color: theme.iconColor, + lineHeight: theme.height + 'px', + paddingLeft: spacing.desktopGutter, }, hover: { - color: Colors.darkBlack, + color: theme.hoverColor, }, }, span: { float: 'left', - color: this.getTheme().iconColor, - lineHeight: this.getTheme().height + 'px', + color: theme.iconColor, + lineHeight: theme.height + 'px', }, }; diff --git a/src/utils/color-manipulator.js b/src/utils/color-manipulator.js index b6b44d1200b741..67d307648dbd29 100644 --- a/src/utils/color-manipulator.js +++ b/src/utils/color-manipulator.js @@ -14,7 +14,7 @@ export default { * * Formula: http://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef */ - _luminance(color) { + luminance(color) { color = this._decomposeColor(color); if (color.type.indexOf('rgb') > -1) { @@ -97,8 +97,8 @@ export default { return this._convertColorToString(color, amount); }, - // Desaturates rgb and sets opacity to 0.15 - lighten(color, amount) { + // Desaturates rgb and sets opacity (defaults to 0.15) + lighten(color, amount, opacity = '0.15') { color = this._decomposeColor(color); if (color.type.indexOf('hsl') > -1) { @@ -113,7 +113,7 @@ export default { if (color.type.indexOf('a') <= -1) color.type += 'a'; - return this._convertColorToString(color, '0.15'); + return this._convertColorToString(color, opacity); }, darken(color, amount) { @@ -137,8 +137,8 @@ export default { // // Formula: http://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef contrastRatio(background, foreground) { - let lumA = this._luminance(background); - let lumB = this._luminance(foreground); + let lumA = this.luminance(background); + let lumB = this.luminance(foreground); if (lumA >= lumB) { return ((lumA + 0.05) / (lumB + 0.05)).toFixed(2);