diff --git a/blocks/color-mechanism/index.js b/blocks/color-mechanism/index.js new file mode 100644 index 0000000000000..6d564304b9871 --- /dev/null +++ b/blocks/color-mechanism/index.js @@ -0,0 +1,48 @@ +/** + * External dependencies + */ +import { find, kebabCase } from 'lodash'; + +/** + * Internal dependencies + */ +import './style.scss'; + +const ALLOWED_COLOR_CONTEXTS = [ + 'background', + 'text', +]; + +export const getColorFromAttribute = ( colors ) => ( colorAttribute ) => { + if ( ! colorAttribute || colorAttribute[ 0 ] !== '%' ) { + return colorAttribute; + } + const colorObj = find( colors, { name: colorAttribute.slice( 1 ) } ); + if ( ! colorObj ) { + return null; + } + return colorObj.color; +}; +export const getAttributeFromColor = ( colors ) => ( color ) => { + const colorObj = find( colors, { color } ); + if ( colorObj ) { + return '%' + colorObj.name; + } + return color; +}; + +export function getClassFromAttribute( colorContext, colorAttribute ) { + if ( ! colorContext || find( ALLOWED_COLOR_CONTEXTS, colorContext ) ) { + if ( window ) { + window.console.error( 'An invalid color context was passed.' ); + } + return null; + } + + if ( ! colorAttribute || colorAttribute[ 0 ] !== '%' ) { + return null; + } + + return `has-${ kebabCase( colorAttribute.slice( 1 ) ) }-${ colorContext }-color`; +} + diff --git a/blocks/color-mechanism/style.scss b/blocks/color-mechanism/style.scss new file mode 100644 index 0000000000000..dd7e469ec5630 --- /dev/null +++ b/blocks/color-mechanism/style.scss @@ -0,0 +1,109 @@ +p.has-pale-pink-background-color, +.wp-block-button.has-pale-pink-background-color .wp-block-button__link { + background-color: #f78da7; +} + +p.has-vivid-red-background-color, +.wp-block-button.has-vivid-red-background-color .wp-block-button__link { + background-color: #cf2e2e; +} + +p.has-luminous-vivid-orange-background-color, +.wp-block-button.has-luminous-vivid-orange-background-color .wp-block-button__link { + background-color: #ff6900; +} + +p.has-luminous-vivid-amber-background-color, +.wp-block-button.has-luminous-vivid-amber-background-color .wp-block-button__link { + background-color: #fcb900; +} + +p.has-light-green-cyan-background-color, +.wp-block-button.has-light-green-cyan-background-color .wp-block-button__link { + background-color: #7bdcb5; +} + +p.has-vivid-green-cyan-background-color, +.wp-block-button.has-vivid-green-cyan-background-color .wp-block-button__link { + background-color: #00d084; +} + +p.has-pale-cyan-blue-background-color, +.wp-block-button.has-pale-cyan-blue-background-color .wp-block-button__link { + background-color: #8ed1fc; +} + +p.has-vivid-cyan-blue-background-color, +.wp-block-button.has-vivid-cyan-blue-background-color .wp-block-button__link { + background-color: #0693e3; +} + +p.has-very-light-gray-background-color, +.wp-block-button.has-very-light-gray-background-color .wp-block-button__link { + background-color: #eeeeee; +} + +p.has-cyan-bluish-gray-background-color, +.wp-block-button.has-cyan-bluish-gray-background-color .wp-block-button__link { + background-color: #abb8c3; +} + +p.has-very-dark-gray-background-color, +.wp-block-button.has-very-dark-gray-background-color .wp-block-button__link { + background-color: #313131; +} + +p.has-pale-pink-text-color, +.wp-block-button.has-pale-pink-text-color .wp-block-button__link { + color: #f78da7; +} + +p.has-vivid-red-text-color, +.wp-block-button.has-vivid-red-text-color .wp-block-button__link { + color: #cf2e2e; +} + +p.has-luminous-vivid-orange-text-color, +.wp-block-button.has-luminous-vivid-orange-text-color .wp-block-button__link { + color: #ff6900; +} + +p.has-luminous-vivid-amber-text-color, +.wp-block-button.has-luminous-vivid-amber-text-color .wp-block-button__link { + color: #fcb900; +} + +p.has-light-green-cyan-text-color, +.wp-block-button.has-light-green-cyan-text-color .wp-block-button__link { + color: #7bdcb5; +} + +p.has-vivid-green-cyan-text-color, +.wp-block-button.has-vivid-green-cyan-text-color .wp-block-button__link { + color: #00d084; +} + +p.has-pale-cyan-blue-text-color, +.wp-block-button.has-pale-cyan-blue-text-color .wp-block-button__link { + color: #8ed1fc; +} + +p.has-vivid-cyan-blue-text-color, +.wp-block-button.has-vivid-cyan-blue-text-color .wp-block-button__link { + color: #0693e3; +} + +p.has-very-light-gray-text-color, +.wp-block-button.has-very-light-gray-text-color .wp-block-button__link { + color: #eeeeee; +} + +p.has-cyan-bluish-gray-text-color, +.wp-block-button.has-cyan-bluish-gray-text-color .wp-block-button__link { + color: #abb8c3; +} + +p.has-very-dark-gray-text-color, +.wp-block-button.has-very-dark-gray-text-color .wp-block-button__link { + color: #313131; +} diff --git a/blocks/color-palette/index.js b/blocks/color-palette/index.js index cd540ada1b4c6..0f43d72400d18 100644 --- a/blocks/color-palette/index.js +++ b/blocks/color-palette/index.js @@ -23,7 +23,7 @@ export function ColorPalette( { colors, disableCustomColors = false, value, onCh return (
- { map( colors, ( color ) => { + { map( colors, ( { name, color } ) => { const style = { color: color }; const className = classnames( 'blocks-color-palette__item', { 'is-active': value === color } ); @@ -34,7 +34,7 @@ export function ColorPalette( { colors, disableCustomColors = false, value, onCh className={ className } style={ style } onClick={ applyOrUnset( color ) } - aria-label={ sprintf( __( 'Color: %s' ), color ) } + aria-label={ sprintf( __( 'Color: %s' ), name || color ) } aria-pressed={ value === color } />
diff --git a/blocks/hooks/colors.js b/blocks/hooks/colors.js new file mode 100644 index 0000000000000..3d8d0d315e16e --- /dev/null +++ b/blocks/hooks/colors.js @@ -0,0 +1,41 @@ +/** + * WordPress dependencies + */ +import { getWrapperDisplayName } from '@wordpress/element'; +import { addFilter } from '@wordpress/hooks'; +import { withContext } from '@wordpress/components'; + +/** + * Internal dependencies + */ +import { getAttributeFromColor, getColorFromAttribute } from '../color-mechanism'; + +/** + * Override the default edit UI to include a new block inspector control for + * assigning the custom class name, if block supports custom class name. + * + * @param {function|Component} BlockEdit Original component. + * + * @return {string} Wrapped component. + */ +export function withColorMechanism( BlockEdit ) { + const BlockEditWithColorContext = withContext( 'editor' )( + ( settings, props ) => ( settings ? { + getAttributeFromColor: getAttributeFromColor( settings.colors ), + getColorFromAttribute: getColorFromAttribute( settings.colors ), + setColorAttributeByColor: ( attribute ) => ( color ) => { + const attributeValue = getAttributeFromColor( settings.colors )( color ); + props.setAttributes( { [ attribute ]: attributeValue || color } ); + }, + } : {} ) + )( BlockEdit ); + + const WrappedBlockEdit = ( props ) => { + return ; + }; + WrappedBlockEdit.displayName = getWrapperDisplayName( BlockEdit, 'colorMechanism' ); + + return WrappedBlockEdit; +} + +addFilter( 'blocks.BlockEdit', 'core/color-mechanism', withColorMechanism ); diff --git a/blocks/hooks/index.js b/blocks/hooks/index.js index 0055037fa07f2..e326723ee7f6b 100644 --- a/blocks/hooks/index.js +++ b/blocks/hooks/index.js @@ -3,6 +3,7 @@ */ import './align'; import './anchor'; +import './colors'; import './custom-class-name'; import './deprecated'; import './generated-class-name'; diff --git a/blocks/library/button/index.js b/blocks/library/button/index.js index fdcf21f6f3844..e396c87a667ca 100644 --- a/blocks/library/button/index.js +++ b/blocks/library/button/index.js @@ -1,3 +1,8 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + /** * WordPress dependencies */ @@ -17,6 +22,7 @@ import BlockAlignmentToolbar from '../../block-alignment-toolbar'; import ColorPalette from '../../color-palette'; import ContrastChecker from '../../contrast-checker'; import InspectorControls from '../../inspector-controls'; +import { getClassFromAttribute } from '../../color-mechanism'; const { getComputedStyle } = window; @@ -61,6 +67,8 @@ class ButtonBlock extends Component { setAttributes, isSelected, className, + getColorFromAttribute, + setColorAttributeByColor, } = this.props; const { @@ -73,13 +81,18 @@ class ButtonBlock extends Component { clear, } = attributes; + const textColorClass = getClassFromAttribute( 'text', textColor ); + const backgroundColorClass = getClassFromAttribute( 'background', color ); + const textColorValue = getColorFromAttribute( textColor ); + const backgroundColorValue = getColorFromAttribute( color ); + return [ isSelected && ( ), - + - + setAttributes( { color: colorValue } ) } + value={ backgroundColorValue } + onChange={ setColorAttributeByColor( 'color' ) } /> - + setAttributes( { textColor: colorValue } ) } + value={ textColorValue } + onChange={ setColorAttributeByColor( 'textColor' ) } /> { this.nodeRef && } } @@ -201,16 +214,18 @@ export const settings = { save( { attributes } ) { const { url, text, title, align, color, textColor } = attributes; + const backgroundClass = getClassFromAttribute( 'background', color ); + const textClass = getClassFromAttribute( 'text', textColor ); const buttonStyle = { - backgroundColor: color, - color: textColor, + backgroundColor: ! backgroundClass ? color : undefined, + color: ! textClass ? textColor : undefined, }; const linkClass = 'wp-block-button__link'; return ( -
+
{ text } diff --git a/blocks/library/paragraph/editor.scss b/blocks/library/paragraph/editor.scss index a50c04177658f..d6ce95eae740f 100644 --- a/blocks/library/paragraph/editor.scss +++ b/blocks/library/paragraph/editor.scss @@ -1,3 +1,3 @@ -.editor-block-list__block:not( .is-multi-selected ) .wp-block-paragraph { +.editor-block-list__block:not( .is-multi-selected ) .wp-block-paragraph:not( .has-background ) { background: white; } diff --git a/blocks/library/paragraph/index.js b/blocks/library/paragraph/index.js index f31fa3d1374d6..c5c32c9cc1c9c 100644 --- a/blocks/library/paragraph/index.js +++ b/blocks/library/paragraph/index.js @@ -31,6 +31,7 @@ import RichText from '../../rich-text'; import InspectorControls from '../../inspector-controls'; import ColorPalette from '../../color-palette'; import ContrastChecker from '../../contrast-checker'; +import { getClassFromAttribute } from '../../color-mechanism'; const { getComputedStyle } = window; @@ -89,6 +90,8 @@ class ParagraphBlock extends Component { isSelected, mergeBlocks, onReplace, + getColorFromAttribute, + setColorAttributeByColor, } = this.props; const { @@ -104,6 +107,11 @@ class ParagraphBlock extends Component { const className = dropCap ? 'has-drop-cap' : null; + const textColorClass = getClassFromAttribute( 'text', textColor ); + const backgroundColorClass = getClassFromAttribute( 'background', backgroundColor ); + const textColorValue = getColorFromAttribute( textColor ); + const backgroundColorValue = getColorFromAttribute( backgroundColor ); + return [ isSelected && ( @@ -133,22 +141,22 @@ class ParagraphBlock extends Component { allowReset /> - + setAttributes( { backgroundColor: colorValue } ) } + value={ backgroundColorValue } + onChange={ setColorAttributeByColor( 'backgroundColor' ) } /> - + setAttributes( { textColor: colorValue } ) } + value={ textColorValue } + onChange={ setColorAttributeByColor( 'textColor' ) } /> { this.nodeRef && = 18 } /> } @@ -169,10 +177,12 @@ class ParagraphBlock extends Component { tagName="p" className={ classnames( 'wp-block-paragraph', className, { 'has-background': backgroundColor, + [ backgroundColorClass ]: backgroundColorClass, + [ textColorClass ]: textColorClass, } ) } style={ { - backgroundColor: backgroundColor, - color: textColor, + backgroundColor: ! backgroundColorClass ? backgroundColorValue : undefined, + color: ! textColorClass ? textColorValue : undefined, fontSize: fontSize ? fontSize + 'px' : undefined, textAlign: align, } } @@ -313,14 +323,19 @@ export const settings = { save( { attributes } ) { const { width, align, content, dropCap, backgroundColor, textColor, fontSize } = attributes; + const backgroundClass = getClassFromAttribute( 'background', backgroundColor ); + const textClass = getClassFromAttribute( 'text', textColor ); + const className = classnames( { [ `align${ width }` ]: width, 'has-background': backgroundColor, 'has-drop-cap': dropCap, + [ backgroundClass ]: backgroundClass, + [ textClass ]: textClass, } ); const styles = { - backgroundColor: backgroundColor, - color: textColor, + backgroundColor: ! backgroundClass ? backgroundColor : undefined, + color: ! textClass ? textColor : undefined, fontSize: fontSize, textAlign: align, }; diff --git a/editor/components/provider/index.js b/editor/components/provider/index.js index 1258e274e21d1..53d8a12f3f3dc 100644 --- a/editor/components/provider/index.js +++ b/editor/components/provider/index.js @@ -33,17 +33,48 @@ import store from '../../store'; const DEFAULT_SETTINGS = { alignWide: false, colors: [ - '#f78da7', - '#cf2e2e', - '#ff6900', - '#fcb900', - '#7bdcb5', - '#00d084', - '#8ed1fc', - '#0693e3', - '#eee', - '#abb8c3', - '#313131', + { name: 'pale pink', + color: '#f78da7', + }, + { name: 'vivid red', + color: '#cf2e2e', + }, + { + name: 'luminous vivid orange', + color: '#ff6900', + }, + { + name: 'luminous vivid amber', + color: '#fcb900', + }, + { + name: 'light green cyan', + color: '#7bdcb5', + }, + { + name: 'vivid green cyan', + color: '#00d084', + }, + { + name: 'pale cyan-blue', + color: '#8ed1fc', + }, + { + name: 'vivid cyan-blue', + color: '#0693e3', + }, + { + name: 'very light gray', + color: '#eeeeee', + }, + { + name: 'cyan-bluish gray', + color: '#abb8c3', + }, + { + name: 'very dark gray', + color: '#313131', + }, ], // This is current max width of the block inner area