From de425c9efbc17a4706ae07ed98950b45a9388852 Mon Sep 17 00:00:00 2001 From: Daniel Dudzic Date: Mon, 19 Jun 2023 11:42:37 +0200 Subject: [PATCH] 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 --- .../assets/js/blocks/mini-cart/block.tsx | 27 ++-- .../blocks/mini-cart/component-frontend.tsx | 3 + .../assets/js/blocks/mini-cart/edit.tsx | 136 ++++++++++++++++-- .../assets/js/blocks/mini-cart/index.tsx | 24 +++- .../blocks/mini-cart/quantity-badge/index.tsx | 18 ++- .../assets/js/blocks/mini-cart/types.ts | 5 +- .../src/BlockTypes/MiniCart.php | 35 +++-- 7 files changed, 208 insertions(+), 40 deletions(-) diff --git a/plugins/woocommerce-blocks/assets/js/blocks/mini-cart/block.tsx b/plugins/woocommerce-blocks/assets/js/blocks/mini-cart/block.tsx index 0bc56b682f0..4cd8150136a 100644 --- a/plugins/woocommerce-blocks/assets/js/blocks/mini-cart/block.tsx +++ b/plugins/woocommerce-blocks/assets/js/blocks/mini-cart/block.tsx @@ -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 ( <> { 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 ?? '', diff --git a/plugins/woocommerce-blocks/assets/js/blocks/mini-cart/edit.tsx b/plugins/woocommerce-blocks/assets/js/blocks/mini-cart/edit.tsx index e125aa5b7b5..5441474f712 100644 --- a/plugins/woocommerce-blocks/assets/js/blocks/mini-cart/edit.tsx +++ b/plugins/woocommerce-blocks/assets/js/blocks/mini-cart/edit.tsx @@ -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 (
@@ -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 => { + { colorGradientSettings.hasColorsOrGradients && ( + // @ts-to-do: Fix outdated InspectorControls type definitions in DefinitelyTyped and/or Gutenberg. + + { colorSettings.map( + ( { onChange, label, value, resetAllFilter } ) => ( + + ) + ) } + + ) } @@ -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; diff --git a/plugins/woocommerce-blocks/assets/js/blocks/mini-cart/index.tsx b/plugins/woocommerce-blocks/assets/js/blocks/mini-cart/index.tsx index a2b0ef3b738..01d09f3a88e 100644 --- a/plugins/woocommerce-blocks/assets/js/blocks/mini-cart/index.tsx +++ b/plugins/woocommerce-blocks/assets/js/blocks/mini-cart/index.tsx @@ -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() { diff --git a/plugins/woocommerce-blocks/assets/js/blocks/mini-cart/quantity-badge/index.tsx b/plugins/woocommerce-blocks/assets/js/blocks/mini-cart/quantity-badge/index.tsx index d25aec2ea0f..c026f429f4e 100644 --- a/plugins/woocommerce-blocks/assets/js/blocks/mini-cart/quantity-badge/index.tsx +++ b/plugins/woocommerce-blocks/assets/js/blocks/mini-cart/quantity-badge/index.tsx @@ -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 => { - + { count > 0 ? count : '' } diff --git a/plugins/woocommerce-blocks/assets/js/blocks/mini-cart/types.ts b/plugins/woocommerce-blocks/assets/js/blocks/mini-cart/types.ts index a90f05c039e..4ce83692fe3 100644 --- a/plugins/woocommerce-blocks/assets/js/blocks/mini-cart/types.ts +++ b/plugins/woocommerce-blocks/assets/js/blocks/mini-cart/types.ts @@ -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; } diff --git a/plugins/woocommerce-blocks/src/BlockTypes/MiniCart.php b/plugins/woocommerce-blocks/src/BlockTypes/MiniCart.php index e25b261f45f..b7291033fd9 100644 --- a/plugins/woocommerce-blocks/src/BlockTypes/MiniCart.php +++ b/plugins/woocommerce-blocks/src/BlockTypes/MiniCart.php @@ -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 '' . $this->get_include_tax_label_markup(); + return '' . $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 "'; + return ''; } /** @@ -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 = ' - - - - + $icon = ' + + + + '; if ( isset( $attributes['miniCartIcon'] ) ) { if ( 'bag' == $attributes['miniCartIcon'] ) { $icon = ' - - - + + + '; } elseif ( 'bag-alt' == $attributes['miniCartIcon'] ) { $icon = ' - - + + '; } } @@ -450,7 +457,7 @@ class MiniCart extends AbstractBlock { $button_html = $this->get_cart_price_markup( $attributes ) . ' ' . $icon . ' - + '; if ( is_cart() || is_checkout() ) {