diff --git a/blocks/color-mechanism/index.js b/blocks/color-mechanism/index.js
new file mode 100644
index 00000000000000..efe882e73bdd70
--- /dev/null
+++ b/blocks/color-mechanism/index.js
@@ -0,0 +1,90 @@
+/**
+ * External dependencies
+ */
+import { find, get, kebabCase } from 'lodash';
+
+/**
+ * WordPress dependencies
+ */
+import { getWrapperDisplayName } from '@wordpress/element';
+import { withContext } from '@wordpress/components';
+
+/**
+ * Internal dependencies
+ */
+import './style.scss';
+
+const getColorValue = ( colors, namedColor, customColor ) => {
+ if ( namedColor ) {
+ const colorObj = find( colors, { name: namedColor } );
+ return colorObj && colorObj.color;
+ }
+ if ( customColor ) {
+ return customColor;
+ }
+};
+
+const setColorValue = ( colors, colorAttributeName, customColorAttributeName, setAttributes ) =>
+ ( colorValue ) => {
+ const colorObj = find( colors, { color: colorValue } );
+ if ( colorObj ) {
+ setAttributes( {
+ [ colorAttributeName ]: colorObj.name,
+ [ customColorAttributeName ]: undefined,
+ } );
+ return;
+ }
+ setAttributes( {
+ [ colorAttributeName ]: undefined,
+ [ customColorAttributeName ]: colorValue,
+ } );
+ };
+
+/**
+ * Returns a class based on the context a color is being used and its name.
+ *
+ * @param {string} colorContextName Context/place where color is being used e.g: background, text etc...
+ * @param {string} colorName Name of the color.
+ *
+ * @return {string} String with the class corresponding to the color in the provided context.
+ */
+export function getColorClass( colorContextName, colorName ) {
+ if ( ! colorContextName || ! colorName ) {
+ return undefined;
+ }
+
+ return `has-${ kebabCase( colorName ) }-${ colorContextName }-color`;
+}
+
+/**
+ * Higher-order component, which handles color logic for class generation
+ * color value, retrieval and color attribute setting.
+ *
+ * @param {WPElement} WrappedComponent The wrapped component.
+ *
+ * @return {Component} Component with a new colors prop.
+ */
+export function withColors( WrappedComponent ) {
+ const ComponentWithColorContext = withContext( 'editor' )(
+ ( settings, props ) => {
+ const colors = get( settings, 'colors', [] );
+ return {
+ colors: ( colorContextName, colorAttributeName, customColorAttributeName ) => ( {
+ value: getColorValue(
+ colors,
+ props.attributes[ colorAttributeName ],
+ props.attributes[ customColorAttributeName ]
+ ),
+ class: getColorClass( colorContextName, props.attributes[ colorAttributeName ] ),
+ set: setColorValue( colors, colorAttributeName, customColorAttributeName, props.setAttributes ),
+ } ),
+ };
+ } )( WrappedComponent );
+
+ const NewComponent = ( props ) => {
+ return ;
+ };
+ NewComponent.displayName = getWrapperDisplayName( WrappedComponent, 'colorMechanism' );
+
+ return NewComponent;
+}
diff --git a/blocks/color-mechanism/style.scss b/blocks/color-mechanism/style.scss
new file mode 100644
index 00000000000000..4928e65e4065a0
--- /dev/null
+++ b/blocks/color-mechanism/style.scss
@@ -0,0 +1,87 @@
+p.has-pale-pink-background-color {
+ background-color: #f78da7;
+}
+
+p.has-vivid-red-background-color {
+ background-color: #cf2e2e;
+}
+
+p.has-luminous-vivid-orange-background-color {
+ background-color: #ff6900;
+}
+
+p.has-luminous-vivid-amber-background-color {
+ background-color: #fcb900;
+}
+
+p.has-light-green-cyan-background-color {
+ background-color: #7bdcb5;
+}
+
+p.has-vivid-green-cyan-background-color {
+ background-color: #00d084;
+}
+
+p.has-pale-cyan-blue-background-color {
+ background-color: #8ed1fc;
+}
+
+p.has-vivid-cyan-blue-background-color {
+ background-color: #0693e3;
+}
+
+p.has-very-light-gray-background-color {
+ background-color: #eeeeee;
+}
+
+p.has-cyan-bluish-gray-background-color {
+ background-color: #abb8c3;
+}
+
+p.has-very-dark-gray-background-color {
+ background-color: #313131;
+}
+
+p.has-pale-pink-text-color {
+ color: #f78da7;
+}
+
+p.has-vivid-red-text-color {
+ color: #cf2e2e;
+}
+
+p.has-luminous-vivid-orange-text-color {
+ color: #ff6900;
+}
+
+p.has-luminous-vivid-amber-text-color {
+ color: #fcb900;
+}
+
+p.has-light-green-cyan-text-color {
+ color: #7bdcb5;
+}
+
+p.has-vivid-green-cyan-text-color {
+ color: #00d084;
+}
+
+p.has-pale-cyan-blue-text-color {
+ color: #8ed1fc;
+}
+
+p.has-vivid-cyan-blue-text-color {
+ color: #0693e3;
+}
+
+p.has-very-light-gray-text-color {
+ color: #eeeeee;
+}
+
+p.has-cyan-bluish-gray-text-color {
+ color: #abb8c3;
+}
+
+p.has-very-dark-gray-text-color {
+ color: #313131;
+}
diff --git a/blocks/color-palette/index.js b/blocks/color-palette/index.js
index cd540ada1b4c64..332dcc52b6ddfe 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, ( { color } ) => {
const style = { color: color };
const className = classnames( 'blocks-color-palette__item', { 'is-active': value === color } );
diff --git a/blocks/color-palette/test/index.js b/blocks/color-palette/test/index.js
index 96ddc339cdf94a..f8bc82d7ce8e7e 100644
--- a/blocks/color-palette/test/index.js
+++ b/blocks/color-palette/test/index.js
@@ -9,7 +9,7 @@ import { shallow } from 'enzyme';
import { ColorPalette } from '../';
describe( 'ColorPalette', () => {
- const colors = [ 'red', 'white', 'blue' ];
+ const colors = [ { name: 'red', color: 'red' }, { name: 'white', color: 'white' }, { name: 'blue', color: 'blue' } ];
const currentColor = 'red';
const onChange = jest.fn();
diff --git a/blocks/library/paragraph/editor.scss b/blocks/library/paragraph/editor.scss
index e5fe10296b7f15..2149aadb63e835 100644
--- a/blocks/library/paragraph/editor.scss
+++ b/blocks/library/paragraph/editor.scss
@@ -1,4 +1,4 @@
-.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 d7cefb196a329f..65bf8714325055 100644
--- a/blocks/library/paragraph/index.js
+++ b/blocks/library/paragraph/index.js
@@ -34,6 +34,7 @@ import RichText from '../../rich-text';
import InspectorControls from '../../inspector-controls';
import ColorPalette from '../../color-palette';
import ContrastChecker from '../../contrast-checker';
+import { getColorClass, withColors } from '../../color-mechanism';
const { getComputedStyle } = window;
@@ -129,6 +130,7 @@ class ParagraphBlock extends Component {
mergeBlocks,
onReplace,
className,
+ colors,
} = this.props;
const {
@@ -136,13 +138,14 @@ class ParagraphBlock extends Component {
content,
dropCap,
placeholder,
- backgroundColor,
- textColor,
width,
} = attributes;
const fontSize = this.getFontSize();
+ const textColor = colors( 'text', 'textColor', 'customTextColor' );
+ const backgroundColor = colors( 'background', 'backgroundColor', 'customBackgroundColor' );
+
return [
isSelected && (
@@ -198,22 +201,22 @@ class ParagraphBlock extends Component {
onChange={ this.toggleDropCap }
/>
-
+
setAttributes( { backgroundColor: colorValue } ) }
+ value={ backgroundColor.value }
+ onChange={ backgroundColor.set }
/>
-
+
setAttributes( { textColor: colorValue } ) }
+ value={ textColor.value }
+ onChange={ textColor.set }
/>
{ this.nodeRef && = 18 }
/> }
@@ -233,12 +236,14 @@ class ParagraphBlock extends Component {