Skip to content

Commit

Permalink
Revert the button block to the previous markup (#21923)
Browse files Browse the repository at this point in the history
* Revert the button block to the previous markup

* Add new markup deprecation

* Fix unit tests
  • Loading branch information
youknowriad authored Apr 27, 2020
1 parent caf52c1 commit 0c6e369
Show file tree
Hide file tree
Showing 21 changed files with 550 additions and 66 deletions.
12 changes: 12 additions & 0 deletions packages/block-library/src/button/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@
},
"borderRadius": {
"type": "number"
},
"style": {
"type": "object"
},
"backgroundColor": {
"type": "string"
},
"textColor": {
"type": "string"
},
"gradient": {
"type": "string"
}
}
}
222 changes: 222 additions & 0 deletions packages/block-library/src/button/color-edit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
/**
* External dependencies
*/
import { pickBy, isEqual, isObject, identity, mapValues } from 'lodash';

/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { useState, useEffect, useRef } from '@wordpress/element';
import { useSelect } from '@wordpress/data';

/**
* Internal dependencies
*/
import {
getColorObjectByColorValue,
getColorObjectByAttributeValues,
getGradientValueBySlug,
getGradientSlugByValue,
__experimentalPanelColorGradientSettings as PanelColorGradientSettings,
ContrastChecker,
InspectorControls,
} from '@wordpress/block-editor';

// The code in this file is copied entirely from the "color" and "style" support flags
// The flag can't be used at the moment because of the extra wrapper around
// the button block markup.

This comment has been minimized.

Copy link
@ellatrix

ellatrix Nov 3, 2020

Member

@youknowriad Is there no other way to do this? This becomes hard to maintain.

This comment has been minimized.

Copy link
@youknowriad

youknowriad Nov 3, 2020

Author Contributor

:( each time I see this code, I'm sad. I wish we could remove that useless div and just use block supports :(.
I'm really unsure at this point how we can make this change in a 100% backward-compatible way.


function getBlockDOMNode( clientId ) {
return document.getElementById( 'block-' + clientId );
}

/**
* Removed undefined values from nested object.
*
* @param {*} object
* @return {*} Object cleaned from undefined values
*/
const cleanEmptyObject = ( object ) => {
if ( ! isObject( object ) ) {
return object;
}
const cleanedNestedObjects = pickBy(
mapValues( object, cleanEmptyObject ),
identity
);
return isEqual( cleanedNestedObjects, {} )
? undefined
: cleanedNestedObjects;
};

function ColorPanel( { settings, clientId, enableContrastChecking = true } ) {
const { getComputedStyle, Node } = window;

const [ detectedBackgroundColor, setDetectedBackgroundColor ] = useState();
const [ detectedColor, setDetectedColor ] = useState();

useEffect( () => {
if ( ! enableContrastChecking ) {
return;
}

const colorsDetectionElement = getBlockDOMNode( clientId );
if ( ! colorsDetectionElement ) {
return;
}
setDetectedColor( getComputedStyle( colorsDetectionElement ).color );

let backgroundColorNode = colorsDetectionElement;
let backgroundColor = getComputedStyle( backgroundColorNode )
.backgroundColor;
while (
backgroundColor === 'rgba(0, 0, 0, 0)' &&
backgroundColorNode.parentNode &&
backgroundColorNode.parentNode.nodeType === Node.ELEMENT_NODE
) {
backgroundColorNode = backgroundColorNode.parentNode;
backgroundColor = getComputedStyle( backgroundColorNode )
.backgroundColor;
}

setDetectedBackgroundColor( backgroundColor );
} );

return (
<InspectorControls>
<PanelColorGradientSettings
title={ __( 'Color settings' ) }
initialOpen={ false }
settings={ settings }
>
{ enableContrastChecking && (
<ContrastChecker
backgroundColor={ detectedBackgroundColor }
textColor={ detectedColor }
/>
) }
</PanelColorGradientSettings>
</InspectorControls>
);
}

/**
* Inspector control panel containing the color related configuration
*
* @param {Object} props
*
* @return {WPElement} Color edit element.
*/
function ColorEdit( props ) {
const { attributes } = props;
const { colors, gradients } = useSelect( ( select ) => {
return select( 'core/block-editor' ).getSettings();
}, [] );
// Shouldn't be needed but right now the ColorGradientsPanel
// can trigger both onChangeColor and onChangeBackground
// synchronously causing our two callbacks to override changes
// from each other.
const localAttributes = useRef( attributes );
useEffect( () => {
localAttributes.current = attributes;
}, [ attributes ] );

const { style, textColor, backgroundColor, gradient } = attributes;
let gradientValue;
if ( gradient ) {
gradientValue = getGradientValueBySlug( gradients, gradient );
} else {
gradientValue = style?.color?.gradient;
}

const onChangeColor = ( name ) => ( value ) => {
const colorObject = getColorObjectByColorValue( colors, value );
const attributeName = name + 'Color';
const newStyle = {
...localAttributes.current.style,
color: {
...localAttributes.current?.style?.color,
[ name ]: colorObject?.slug ? undefined : value,
},
};

const newNamedColor = colorObject?.slug ? colorObject.slug : undefined;
const newAttributes = {
style: cleanEmptyObject( newStyle ),
[ attributeName ]: newNamedColor,
};

props.setAttributes( newAttributes );
localAttributes.current = {
...localAttributes.current,
...newAttributes,
};
};

const onChangeGradient = ( value ) => {
const slug = getGradientSlugByValue( gradients, value );
let newAttributes;
if ( slug ) {
const newStyle = {
...localAttributes.current?.style,
color: {
...localAttributes.current?.style?.color,
gradient: undefined,
},
};
newAttributes = {
style: cleanEmptyObject( newStyle ),
gradient: slug,
};
} else {
const newStyle = {
...localAttributes.current?.style,
color: {
...localAttributes.current?.style?.color,
gradient: value,
},
};
newAttributes = {
style: cleanEmptyObject( newStyle ),
gradient: undefined,
};
}
props.setAttributes( newAttributes );
localAttributes.current = {
...localAttributes.current,
...newAttributes,
};
};

return (
<ColorPanel
enableContrastChecking={ ! gradient && ! style?.color?.gradient }
clientId={ props.clientId }
settings={ [
{
label: __( 'Text Color' ),
onColorChange: onChangeColor( 'text' ),
colorValue: getColorObjectByAttributeValues(
colors,
textColor,
style?.color?.text
).color,
},
{
label: __( 'Background Color' ),
onColorChange: onChangeColor( 'background' ),
colorValue: getColorObjectByAttributeValues(
colors,
backgroundColor,
style?.color?.background
).color,
gradientValue,
onGradientChange: onChangeGradient,
},
] }
/>
);
}

export default ColorEdit;
55 changes: 55 additions & 0 deletions packages/block-library/src/button/color-props.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* External dependencies
*/
import classnames from 'classnames';

/**
* WordPress dependencies
*/
import {
getColorClassName,
__experimentalGetGradientClass,
} from '@wordpress/block-editor';

// The code in this file is copied entirely from the "color" and "style" support flags
// The flag can't be used at the moment because of the extra wrapper around
// the button block markup.

export default function getColorAndStyleProps( attributes ) {
// I'd have prefered to avoid the "style" attribute usage here
const { backgroundColor, textColor, gradient, style } = attributes;

const backgroundClass = getColorClassName(
'background-color',
backgroundColor
);
const gradientClass = __experimentalGetGradientClass( gradient );
const textClass = getColorClassName( 'color', textColor );
const className = classnames( textClass, gradientClass, {
// Don't apply the background class if there's a custom gradient
[ backgroundClass ]: ! style?.color?.gradient && !! backgroundClass,
'has-text-color': textColor || style?.color?.text,
'has-background':
backgroundColor ||
style?.color?.background ||
gradient ||
style?.color?.gradient,
} );
const styleProp =
style?.color?.background || style?.color?.text || style?.color?.gradient
? {
background: style?.color?.gradient
? style.color.gradient
: undefined,
backgroundColor: style?.color?.background
? style.color.background
: undefined,
color: style?.color?.text ? style.color.text : undefined,
}
: {};

return {
className: !! className ? className : undefined,
style: styleProp,
};
}
74 changes: 74 additions & 0 deletions packages/block-library/src/button/deprecated.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,75 @@ const blockAttributes = {
};

const deprecated = [
{
supports: {
align: true,
alignWide: false,
__experimentalColor: { gradients: true },
},
attributes: {
...blockAttributes,
linkTarget: {
type: 'string',
source: 'attribute',
selector: 'a',
attribute: 'target',
},
rel: {
type: 'string',
source: 'attribute',
selector: 'a',
attribute: 'rel',
},
placeholder: {
type: 'string',
},
borderRadius: {
type: 'number',
},
backgroundColor: {
type: 'string',
},
textColor: {
type: 'string',
},
gradient: {
type: 'string',
},
style: {
type: 'object',
},
},
save( { attributes } ) {
const {
borderRadius,
linkTarget,
rel,
text,
title,
url,
} = attributes;
const buttonClasses = classnames( 'wp-block-button__link', {
'no-border-radius': borderRadius === 0,
} );
const buttonStyle = {
borderRadius: borderRadius ? borderRadius + 'px' : undefined,
};

return (
<RichText.Content
tagName="a"
className={ buttonClasses }
href={ url }
title={ title }
style={ buttonStyle }
value={ text }
target={ linkTarget }
rel={ rel }
/>
);
},
},
{
supports: {
align: true,
Expand Down Expand Up @@ -125,6 +194,11 @@ const deprecated = [
type: 'string',
},
},

isEligible: ( attributes ) =>
!! attributes.customTextColor ||
!! attributes.customBackgroundColor ||
!! attributes.customGradient,
migrate: migrateCustomColorsAndGradients,
save( { attributes } ) {
const {
Expand Down
Loading

0 comments on commit 0c6e369

Please sign in to comment.