Mini Cart: Add Price, Icon and Product Count color settings (https://github.com/woocommerce/woocommerce-blocks/pull/9647)

* Mini Cart: Update color settings to include Price, Icon and Product Count.

* Fix color settings in the editor.

* Mini Cart: Add color settings for the Price, Icon and Product Count.

* Mini Cart: Remove unnecessary color settings.

* Remove unnecessary code comments.

* Update color settings labels.

* Add price color to the tax label.

* Add missing docs comment

* Fix TS errors

* Fix TS error

* Adjust type declaration

* Add TS error comments

* Change @ts-to-do to @ts-expect-error

---------

Co-authored-by: tjcafferkey <tjcafferkey@gmail.com>
This commit is contained in:
Daniel Dudzic 2023-06-19 11:42:37 +02:00 committed by GitHub
parent 8a6e1cdb76
commit de425c9efb
7 changed files with 208 additions and 40 deletions

View File

@ -53,11 +53,13 @@ const MiniCartBlock = ( attributes: Props ): JSX.Element => {
const {
isInitiallyOpen = false,
colorClassNames,
style,
contents = '',
miniCartIcon,
addToCartBehaviour = 'none',
hasHiddenPrice = false,
priceColorValue,
iconColorValue,
productCountColorValue,
} = attributes;
const {
@ -233,16 +235,10 @@ const MiniCartBlock = ( attributes: Props ): JSX.Element => {
)
);
const colorStyle = {
backgroundColor: style?.color?.background,
color: style?.color?.text,
};
return (
<>
<button
className={ `wc-block-mini-cart__button ${ colorClassNames }` }
style={ colorStyle }
onClick={ () => {
if ( ! isOpen ) {
setIsOpen( true );
@ -252,7 +248,10 @@ const MiniCartBlock = ( attributes: Props ): JSX.Element => {
aria-label={ ariaLabel }
>
{ ! hasHiddenPrice && (
<span className="wc-block-mini-cart__amount">
<span
className="wc-block-mini-cart__amount"
style={ { color: priceColorValue } }
>
{ formatPrice(
subTotal,
getCurrencyFromPriceResponse( cartTotals )
@ -260,11 +259,19 @@ const MiniCartBlock = ( attributes: Props ): JSX.Element => {
</span>
) }
{ taxLabel !== '' && subTotal !== 0 && ! hasHiddenPrice && (
<small className="wc-block-mini-cart__tax-label">
<small
className="wc-block-mini-cart__tax-label"
style={ { color: priceColorValue } }
>
{ taxLabel }
</small>
) }
<QuantityBadge count={ cartItemsCount } icon={ miniCartIcon } />
<QuantityBadge
count={ cartItemsCount }
icon={ miniCartIcon }
iconColor={ iconColorValue }
productCountColor={ productCountColorValue }
/>
</button>
<Drawer
className={ classnames(

View File

@ -44,6 +44,9 @@ const renderMiniCartFrontend = () => {
miniCartIcon: el.dataset.miniCartIcon,
addToCartBehaviour: el.dataset.addToCartBehaviour || 'none',
hasHiddenPrice: el.dataset.hasHiddenPrice,
priceColorValue: el.dataset.priceColorValue,
iconColorValue: el.dataset.iconColorValue,
productCountColorValue: el.dataset.productCountColorValue,
contents:
el.querySelector( '.wc-block-mini-cart__template-part' )
?.innerHTML ?? '',

View File

@ -1,7 +1,13 @@
/**
* External dependencies
*/
import { InspectorControls, useBlockProps } from '@wordpress/block-editor';
import {
InspectorControls,
useBlockProps,
withColors,
__experimentalColorGradientSettingsDropdown as ColorGradientSettingsDropdown,
__experimentalUseMultipleOriginColorsAndGradients as useMultipleOriginColorsAndGradients,
} from '@wordpress/block-editor';
import { formatPrice } from '@woocommerce/price-format';
import {
PanelBody,
@ -17,6 +23,7 @@ import Noninteractive from '@woocommerce/base-components/noninteractive';
import { isSiteEditorPage } from '@woocommerce/utils';
import type { ReactElement } from 'react';
import { select } from '@wordpress/data';
import classNames from 'classnames';
import { cartOutline, bag, bagAlt } from '@woocommerce/icons';
import { Icon } from '@wordpress/icons';
@ -31,24 +38,50 @@ interface Attributes {
addToCartBehaviour: string;
hasHiddenPrice: boolean;
cartAndCheckoutRenderStyle: boolean;
priceColor: string;
iconColor: string;
productCountColor: string;
priceColorValue: string;
iconColorValue: string;
productCountColorValue: string;
}
interface Props {
attributes: Attributes;
setAttributes: ( attributes: Record< string, unknown > ) => void;
clientId: number;
setPriceColor: ( colorValue: string | undefined ) => void;
setIconColor: ( colorValue: string | undefined ) => void;
setProductCountColor: ( colorValue: string | undefined ) => void;
}
const Edit = ( { attributes, setAttributes }: Props ): ReactElement => {
const Edit = ( {
attributes,
setAttributes,
clientId,
setPriceColor,
setIconColor,
setProductCountColor,
}: Props ): ReactElement => {
const {
miniCartIcon,
cartAndCheckoutRenderStyle,
addToCartBehaviour,
hasHiddenPrice,
cartAndCheckoutRenderStyle,
priceColorValue,
iconColorValue,
productCountColorValue,
miniCartIcon,
} = attributes;
const blockProps = useBlockProps( {
className: `wc-block-mini-cart`,
const className = classNames( {
'wc-block-mini-cart': true,
'has-price-color': priceColorValue,
'has-icon-color': iconColorValue,
'has-product-count-color': productCountColorValue,
} );
const blockProps = useBlockProps( { className } );
const isSiteEditor = isSiteEditorPage( select( 'core/edit-site' ) );
const templatePartEditUri = getSetting(
@ -59,6 +92,47 @@ const Edit = ( { attributes, setAttributes }: Props ): ReactElement => {
const productCount = 0;
const productTotal = 0;
const colorGradientSettings = useMultipleOriginColorsAndGradients();
const colorSettings = [
{
value: priceColorValue,
onChange: ( colorValue: string ) => {
setPriceColor( colorValue );
setAttributes( { priceColorValue: colorValue } );
},
label: __( 'Price', 'woo-gutenberg-products-block' ),
resetAllFilter: () => {
setPriceColor( undefined );
setAttributes( { priceColorValue: undefined } );
},
},
{
value: iconColorValue,
onChange: ( colorValue: string ) => {
setIconColor( colorValue );
setAttributes( { iconColorValue: colorValue } );
},
label: __( 'Icon', 'woo-gutenberg-products-block' ),
resetAllFilter: () => {
setIconColor( undefined );
setAttributes( { iconColorValue: undefined } );
},
},
{
value: productCountColorValue,
onChange: ( colorValue: string ) => {
setProductCountColor( colorValue );
setAttributes( { productCountColorValue: colorValue } );
},
label: __( 'Product count', 'woo-gutenberg-products-block' ),
resetAllFilter: () => {
setProductCountColor( undefined );
setAttributes( { productCountColorValue: undefined } );
},
},
];
return (
<div { ...blockProps }>
<InspectorControls>
@ -73,7 +147,7 @@ const Edit = ( { attributes, setAttributes }: Props ): ReactElement => {
'woo-gutenberg-products-block'
) }
value={ miniCartIcon }
onChange={ ( value ) => {
onChange={ ( value: 'cart' | 'bag' | 'bag-alt' ) => {
setAttributes( {
miniCartIcon: value,
} );
@ -124,7 +198,7 @@ const Edit = ( { attributes, setAttributes }: Props ): ReactElement => {
'woo-gutenberg-products-block'
) }
value={ cartAndCheckoutRenderStyle }
onChange={ ( value ) => {
onChange={ ( value: boolean ) => {
setAttributes( {
cartAndCheckoutRenderStyle: value,
} );
@ -212,15 +286,45 @@ const Edit = ( { attributes, setAttributes }: Props ): ReactElement => {
</BaseControl>
</PanelBody>
</InspectorControls>
{ colorGradientSettings.hasColorsOrGradients && (
// @ts-to-do: Fix outdated InspectorControls type definitions in DefinitelyTyped and/or Gutenberg.
<InspectorControls group="color">
{ colorSettings.map(
( { onChange, label, value, resetAllFilter } ) => (
<ColorGradientSettingsDropdown
key={ `mini-cart-color-${ label }` }
__experimentalIsRenderedInSidebar
settings={ [
{
colorValue: value,
label,
onColorChange: onChange,
isShownByDefault: true,
resetAllFilter,
enableAlpha: true,
},
] }
panelId={ clientId }
{ ...colorGradientSettings }
/>
)
) }
</InspectorControls>
) }
<Noninteractive>
<button className="wc-block-mini-cart__button">
{ ! hasHiddenPrice && (
<span className="wc-block-mini-cart__amount">
<span
className="wc-block-mini-cart__amount"
style={ { color: priceColorValue } }
>
{ formatPrice( productTotal ) }
</span>
) }
<QuantityBadge
count={ productCount }
iconColor={ iconColorValue }
productCountColor={ productCountColorValue }
icon={ miniCartIcon }
/>
</button>
@ -229,4 +333,16 @@ const Edit = ( { attributes, setAttributes }: Props ): ReactElement => {
);
};
export default Edit;
const miniCartColorAttributes = {
priceColor: 'price-color',
iconColor: 'icon-color',
productCountColor: 'product-count-color',
};
// @ts-expect-error: TypeScript doesn't resolve the shared React dependency and cannot resolve the type returned by `withColors`.
// Similar issue example: https://github.com/microsoft/TypeScript/issues/47663
const EditWithColors: JSX.Element = withColors( miniCartColorAttributes )(
Edit
);
export default EditWithColors;

View File

@ -30,10 +30,14 @@ const settings: BlockConfiguration = {
'Display a button for shoppers to quickly view their cart.',
'woo-gutenberg-products-block'
),
providesContext: {
priceColorValue: 'priceColorValue',
iconColorValue: 'iconColorValue',
productCountColorValue: 'productCountColorValue',
},
supports: {
html: false,
multiple: false,
color: true,
typography: {
fontSize: true,
...( isFeaturePluginBuild() && {
@ -69,6 +73,24 @@ const settings: BlockConfiguration = {
type: 'string',
default: 'hidden',
},
priceColor: {
type: 'string',
},
priceColorValue: {
type: 'string',
},
iconColor: {
type: 'string',
},
iconColorValue: {
type: 'string',
},
productCountColor: {
type: 'string',
},
productCountColorValue: {
type: 'string',
},
},
edit,
save() {

View File

@ -12,11 +12,17 @@ import { IconType } from '.././types';
interface Props {
count: number;
colorClassNames?: string;
icon?: IconType;
iconColor?: string;
productCountColor?: string;
}
const QuantityBadge = ( { count, icon }: Props ): JSX.Element => {
const QuantityBadge = ( {
count,
icon,
iconColor,
productCountColor,
}: Props ): JSX.Element => {
function getIcon( iconName?: 'cart' | 'bag' | 'bag-alt' ) {
switch ( iconName ) {
case 'cart':
@ -34,10 +40,14 @@ const QuantityBadge = ( { count, icon }: Props ): JSX.Element => {
<span className="wc-block-mini-cart__quantity-badge">
<Icon
className="wc-block-mini-cart__icon"
size={ 32 }
color={ iconColor }
size={ 20 }
icon={ getIcon( icon ) }
/>
<span className="wc-block-mini-cart__badge">
<span
className="wc-block-mini-cart__badge"
style={ { background: productCountColor } }
>
{ count > 0 ? count : '' }
</span>
</span>

View File

@ -1,4 +1,4 @@
export type IconType = 'cart' | 'bag' | 'bag-alt';
export type IconType = 'cart' | 'bag' | 'bag-alt' | undefined;
export interface BlockAttributes {
isInitiallyOpen?: boolean;
@ -8,4 +8,7 @@ export interface BlockAttributes {
miniCartIcon?: IconType;
addToCartBehaviour: string;
hasHiddenPrice: boolean;
priceColorValue: string;
iconColorValue: string;
productCountColorValue: string;
}

View File

@ -374,21 +374,25 @@ class MiniCart extends AbstractBlock {
if ( isset( $attributes['hasHiddenPrice'] ) && false !== $attributes['hasHiddenPrice'] ) {
return;
}
$price_color = array_key_exists( 'priceColorValue', $attributes ) ? $attributes['priceColorValue'] : '';
return '<span class="wc-block-mini-cart__amount"></span>' . $this->get_include_tax_label_markup();
return '<span class="wc-block-mini-cart__amount" style="color:' . $price_color . ' "></span>' . $this->get_include_tax_label_markup( $attributes );
}
/**
* Returns the markup for render the tax label.
*
* @param array $attributes Block attributes.
*
* @return string
*/
protected function get_include_tax_label_markup() {
protected function get_include_tax_label_markup( $attributes ) {
if ( empty( $this->tax_label ) ) {
return '';
}
$price_color = array_key_exists( 'priceColorValue', $attributes ) ? $attributes['priceColorValue'] : '';
return "<small class='wc-block-mini-cart__tax-label' hidden>" . esc_html( $this->tax_label ) . '</small>';
return '<small class="wc-block-mini-cart__tax-label" style="color:' . $price_color . ' " hidden>' . esc_html( $this->tax_label ) . '</small>';
}
/**
@ -424,25 +428,28 @@ class MiniCart extends AbstractBlock {
}
$wrapper_styles = $classes_styles['styles'];
$icon_color = array_key_exists( 'iconColorValue', $attributes ) ? $attributes['iconColorValue'] : 'currentColor';
$product_count_color = array_key_exists( 'productCountColorValue', $attributes ) ? $attributes['productCountColorValue'] : '';
// Default "Cart" icon.
$icon = '<svg class="wc-block-mini-cart__icon" width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="12.6667" cy="24.6667" r="2" fill="black"/>
<circle cx="23.3333" cy="24.6667" r="2" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.28491 10.0356C9.47481 9.80216 9.75971 9.66667 10.0606 9.66667H25.3333C25.6232 9.66667 25.8989 9.79247 26.0888 10.0115C26.2787 10.2305 26.3643 10.5211 26.3233 10.8081L24.99 20.1414C24.9196 20.6341 24.4977 21 24 21H12C11.5261 21 11.1173 20.6674 11.0209 20.2034L9.08153 10.8701C9.02031 10.5755 9.09501 10.269 9.28491 10.0356ZM11.2898 11.6667L12.8136 19H23.1327L24.1803 11.6667H11.2898Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.66669 6.66667C5.66669 6.11438 6.1144 5.66667 6.66669 5.66667H9.33335C9.81664 5.66667 10.2308 6.01229 10.3172 6.48778L11.0445 10.4878C11.1433 11.0312 10.7829 11.5517 10.2395 11.6505C9.69614 11.7493 9.17555 11.3889 9.07676 10.8456L8.49878 7.66667H6.66669C6.1144 7.66667 5.66669 7.21895 5.66669 6.66667Z" fill="black"/>
$icon = '<svg class="wc-block-mini-cart__icon" width="32" height="32" viewBox="0 0 32 32" fill="' . $icon_color . '" xmlns="http://www.w3.org/2000/svg">
<circle cx="12.6667" cy="24.6667" r="2" fill="' . $icon_color . '"/>
<circle cx="23.3333" cy="24.6667" r="2" fill="' . $icon_color . '"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.28491 10.0356C9.47481 9.80216 9.75971 9.66667 10.0606 9.66667H25.3333C25.6232 9.66667 25.8989 9.79247 26.0888 10.0115C26.2787 10.2305 26.3643 10.5211 26.3233 10.8081L24.99 20.1414C24.9196 20.6341 24.4977 21 24 21H12C11.5261 21 11.1173 20.6674 11.0209 20.2034L9.08153 10.8701C9.02031 10.5755 9.09501 10.269 9.28491 10.0356ZM11.2898 11.6667L12.8136 19H23.1327L24.1803 11.6667H11.2898Z" fill="' . $icon_color . '"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.66669 6.66667C5.66669 6.11438 6.1144 5.66667 6.66669 5.66667H9.33335C9.81664 5.66667 10.2308 6.01229 10.3172 6.48778L11.0445 10.4878C11.1433 11.0312 10.7829 11.5517 10.2395 11.6505C9.69614 11.7493 9.17555 11.3889 9.07676 10.8456L8.49878 7.66667H6.66669C6.1144 7.66667 5.66669 7.21895 5.66669 6.66667Z" fill="' . $icon_color . '"/>
</svg>';
if ( isset( $attributes['miniCartIcon'] ) ) {
if ( 'bag' == $attributes['miniCartIcon'] ) {
$icon = '<svg class="wc-block-mini-cart__icon" width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.4444 14.2222C12.9354 14.2222 13.3333 14.6202 13.3333 15.1111C13.3333 15.8183 13.6143 16.4966 14.1144 16.9967C14.6145 17.4968 15.2927 17.7778 16 17.7778C16.7072 17.7778 17.3855 17.4968 17.8856 16.9967C18.3857 16.4966 18.6667 15.8183 18.6667 15.1111C18.6667 14.6202 19.0646 14.2222 19.5555 14.2222C20.0465 14.2222 20.4444 14.6202 20.4444 15.1111C20.4444 16.2898 19.9762 17.4203 19.1427 18.2538C18.3092 19.0873 17.1787 19.5555 16 19.5555C14.8212 19.5555 13.6908 19.0873 12.8573 18.2538C12.0238 17.4203 11.5555 16.2898 11.5555 15.1111C11.5555 14.6202 11.9535 14.2222 12.4444 14.2222Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.2408 6.68254C11.4307 6.46089 11.7081 6.33333 12 6.33333H20C20.2919 6.33333 20.5693 6.46089 20.7593 6.68254L24.7593 11.3492C25.0134 11.6457 25.0717 12.0631 24.9085 12.4179C24.7453 12.7727 24.3905 13 24 13H8.00001C7.60948 13 7.25469 12.7727 7.0915 12.4179C6.92832 12.0631 6.9866 11.6457 7.24076 11.3492L11.2408 6.68254ZM12.4599 8.33333L10.1742 11H21.8258L19.5401 8.33333H12.4599Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M7 12C7 11.4477 7.44772 11 8 11H24C24.5523 11 25 11.4477 25 12V25.3333C25 25.8856 24.5523 26.3333 24 26.3333H8C7.44772 26.3333 7 25.8856 7 25.3333V12ZM9 13V24.3333H23V13H9Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.4444 14.2222C12.9354 14.2222 13.3333 14.6202 13.3333 15.1111C13.3333 15.8183 13.6143 16.4966 14.1144 16.9967C14.6145 17.4968 15.2927 17.7778 16 17.7778C16.7072 17.7778 17.3855 17.4968 17.8856 16.9967C18.3857 16.4966 18.6667 15.8183 18.6667 15.1111C18.6667 14.6202 19.0646 14.2222 19.5555 14.2222C20.0465 14.2222 20.4444 14.6202 20.4444 15.1111C20.4444 16.2898 19.9762 17.4203 19.1427 18.2538C18.3092 19.0873 17.1787 19.5555 16 19.5555C14.8212 19.5555 13.6908 19.0873 12.8573 18.2538C12.0238 17.4203 11.5555 16.2898 11.5555 15.1111C11.5555 14.6202 11.9535 14.2222 12.4444 14.2222Z" fill="' . $icon_color . '""/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M11.2408 6.68254C11.4307 6.46089 11.7081 6.33333 12 6.33333H20C20.2919 6.33333 20.5693 6.46089 20.7593 6.68254L24.7593 11.3492C25.0134 11.6457 25.0717 12.0631 24.9085 12.4179C24.7453 12.7727 24.3905 13 24 13H8.00001C7.60948 13 7.25469 12.7727 7.0915 12.4179C6.92832 12.0631 6.9866 11.6457 7.24076 11.3492L11.2408 6.68254ZM12.4599 8.33333L10.1742 11H21.8258L19.5401 8.33333H12.4599Z" fill="' . $icon_color . '"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M7 12C7 11.4477 7.44772 11 8 11H24C24.5523 11 25 11.4477 25 12V25.3333C25 25.8856 24.5523 26.3333 24 26.3333H8C7.44772 26.3333 7 25.8856 7 25.3333V12ZM9 13V24.3333H23V13H9Z" fill="' . $icon_color . '"/>
</svg>';
} elseif ( 'bag-alt' == $attributes['miniCartIcon'] ) {
$icon = '<svg class="wc-block-mini-cart__icon" width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.5556 12.3333C19.0646 12.3333 18.6667 11.9354 18.6667 11.4444C18.6667 10.7372 18.3857 8.05893 17.8856 7.55883C17.3855 7.05873 16.7073 6.77778 16 6.77778C15.2928 6.77778 14.6145 7.05873 14.1144 7.55883C13.6143 8.05893 13.3333 10.7372 13.3333 11.4444C13.3333 11.9354 12.9354 12.3333 12.4445 12.3333C11.9535 12.3333 11.5556 11.9354 11.5556 11.4444C11.5556 10.2657 12.0238 7.13524 12.8573 6.30175C13.6908 5.46825 14.8213 5 16 5C17.1788 5 18.3092 5.46825 19.1427 6.30175C19.9762 7.13524 20.4445 10.2657 20.4445 11.4444C20.4445 11.9354 20.0465 12.3333 19.5556 12.3333Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.5 12C7.5 11.4477 7.94772 11 8.5 11H23.5C24.0523 11 24.5 11.4477 24.5 12V25.3333C24.5 25.8856 24.0523 26.3333 23.5 26.3333H8.5C7.94772 26.3333 7.5 25.8856 7.5 25.3333V12ZM9.5 13V24.3333H22.5V13H9.5Z" fill="black"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M19.5556 12.3333C19.0646 12.3333 18.6667 11.9354 18.6667 11.4444C18.6667 10.7372 18.3857 8.05893 17.8856 7.55883C17.3855 7.05873 16.7073 6.77778 16 6.77778C15.2928 6.77778 14.6145 7.05873 14.1144 7.55883C13.6143 8.05893 13.3333 10.7372 13.3333 11.4444C13.3333 11.9354 12.9354 12.3333 12.4445 12.3333C11.9535 12.3333 11.5556 11.9354 11.5556 11.4444C11.5556 10.2657 12.0238 7.13524 12.8573 6.30175C13.6908 5.46825 14.8213 5 16 5C17.1788 5 18.3092 5.46825 19.1427 6.30175C19.9762 7.13524 20.4445 10.2657 20.4445 11.4444C20.4445 11.9354 20.0465 12.3333 19.5556 12.3333Z" fill="' . $icon_color . '"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.5 12C7.5 11.4477 7.94772 11 8.5 11H23.5C24.0523 11 24.5 11.4477 24.5 12V25.3333C24.5 25.8856 24.0523 26.3333 23.5 26.3333H8.5C7.94772 26.3333 7.5 25.8856 7.5 25.3333V12ZM9.5 13V24.3333H22.5V13H9.5Z" fill="' . $icon_color . '" />
</svg>';
}
}
@ -450,7 +457,7 @@ class MiniCart extends AbstractBlock {
$button_html = $this->get_cart_price_markup( $attributes ) . '
<span class="wc-block-mini-cart__quantity-badge">
' . $icon . '
<span class="wc-block-mini-cart__badge"></span>
<span class="wc-block-mini-cart__badge" style="background:' . $product_count_color . '"></span>
</span>';
if ( is_cart() || is_checkout() ) {