diff --git a/assets/js/blocks/cart-checkout/mini-cart/block.tsx b/assets/js/blocks/cart-checkout/mini-cart/block.tsx
index eb754c23bd1..31086d5eba8 100644
--- a/assets/js/blocks/cart-checkout/mini-cart/block.tsx
+++ b/assets/js/blocks/cart-checkout/mini-cart/block.tsx
@@ -1,7 +1,7 @@
/**
* External dependencies
*/
-import classNames from 'classnames';
+import classnames from 'classnames';
import { __, _n, sprintf } from '@wordpress/i18n';
import { useState, useEffect, useRef } from '@wordpress/element';
import {
@@ -31,10 +31,6 @@ import CartLineItemsTable from '../cart/cart-line-items-table';
import QuantityBadge from './quantity-badge';
import './style.scss';
-interface MiniCartBlockProps {
- isInitiallyOpen?: boolean;
-}
-
const PaymentMethodIconsElement = (): JSX.Element => {
const { paymentMethods } = usePaymentMethods();
return (
@@ -44,9 +40,18 @@ const PaymentMethodIconsElement = (): JSX.Element => {
);
};
+interface Props {
+ isInitiallyOpen?: boolean;
+ transparentButton: boolean;
+ colorClassNames?: string;
+ style?: Record< string, Record< string, string > >;
+}
+
const MiniCartBlock = ( {
isInitiallyOpen = false,
-}: MiniCartBlockProps ): JSX.Element => {
+ colorClassNames,
+ style,
+}: Props ): JSX.Element => {
const {
cartItems,
cartItemsCount,
@@ -115,6 +120,11 @@ const MiniCartBlock = ( {
formatPrice( subTotal, getCurrencyFromPriceResponse( cartTotals ) )
);
+ const colorStyle = {
+ backgroundColor: style?.color?.background,
+ color: style?.color?.text,
+ };
+
const contents =
! cartIsLoading && cartItems.length === 0 ? (
{
renderFrontend( {
selector: '.wc-block-mini-cart',
Block: MiniCartBlock,
- getProps: ( el: HTMLElement ) => ( {
- isDataOutdated: el.dataset.isDataOutdated,
- isInitiallyOpen: el.dataset.isInitiallyOpen === 'true',
- } ),
+ getProps: ( el: HTMLElement ) => {
+ let colorClassNames = '';
+ const button = el.querySelector( '.wc-block-mini-cart__button' );
+ if ( button !== null ) {
+ colorClassNames = button.classList
+ .toString()
+ .replace( 'wc-block-mini-cart__button', '' );
+ }
+ return {
+ isDataOutdated: el.dataset.isDataOutdated,
+ isInitiallyOpen: el.dataset.isInitiallyOpen === 'true',
+ colorClassNames,
+ style: el.dataset.style ? JSON.parse( el.dataset.style ) : {},
+ };
+ },
} );
// Refocus previously focused button if drawer is not open.
diff --git a/assets/js/blocks/cart-checkout/mini-cart/edit.tsx b/assets/js/blocks/cart-checkout/mini-cart/edit.tsx
index eeaffcf8866..46bc4b56ec3 100644
--- a/assets/js/blocks/cart-checkout/mini-cart/edit.tsx
+++ b/assets/js/blocks/cart-checkout/mini-cart/edit.tsx
@@ -1,19 +1,65 @@
/**
* External dependencies
*/
-import { useBlockProps } from '@wordpress/block-editor';
+import {
+ InspectorControls,
+ useBlockProps,
+ getColorClassName,
+} from '@wordpress/block-editor';
import type { ReactElement } from 'react';
import { formatPrice } from '@woocommerce/price-format';
import { CartCheckoutCompatibilityNotice } from '@woocommerce/editor-components/compatibility-notices';
+import { PanelBody, ToggleControl } from '@wordpress/components';
+import { __ } from '@wordpress/i18n';
+import classnames from 'classnames';
/**
* Internal dependencies
*/
import QuantityBadge from './quantity-badge';
-const MiniCartBlock = (): ReactElement => {
+interface Attributes {
+ isInitiallyOpen?: boolean;
+ transparentButton: boolean;
+ backgroundColor?: string;
+ textColor?: string;
+ style?: Record< string, Record< string, string > >;
+}
+
+interface Props {
+ attributes: Attributes;
+ setAttributes: ( attributes: Record< string, unknown > ) => void;
+}
+
+const MiniCartBlock = ( {
+ attributes,
+ setAttributes,
+}: Props ): ReactElement => {
+ const { transparentButton, backgroundColor, textColor, style } = attributes;
const blockProps = useBlockProps( {
- className: 'wc-block-mini-cart',
+ className: classnames( 'wc-block-mini-cart', {
+ 'is-transparent': transparentButton,
+ } ),
+ } );
+
+ /**
+ * @todo Replace `getColorClassName` and manual style manipulation with
+ * `useColorProps` once the hook is no longer experimental.
+ */
+ const backgroundClass = getColorClassName(
+ 'background-color',
+ backgroundColor
+ );
+ const textColorClass = getColorClassName( 'color', textColor );
+
+ const colorStyle = {
+ backgroundColor: style?.color?.background,
+ color: style?.color?.text,
+ };
+
+ const colorClassNames = classnames( backgroundClass, textColorClass, {
+ 'has-background': backgroundClass || style?.color?.background,
+ 'has-text-color': textColorClass || style?.color?.text,
} );
const productCount = 0;
@@ -21,11 +67,42 @@ const MiniCartBlock = (): ReactElement => {
return (
-
diff --git a/assets/js/blocks/cart-checkout/mini-cart/index.tsx b/assets/js/blocks/cart-checkout/mini-cart/index.tsx
index b07203f29f0..c452add3db6 100644
--- a/assets/js/blocks/cart-checkout/mini-cart/index.tsx
+++ b/assets/js/blocks/cart-checkout/mini-cart/index.tsx
@@ -26,6 +26,19 @@ const settings = {
supports: {
html: false,
multiple: false,
+ color: {
+ /**
+ * Because we don't target the wrapper element, we don't need
+ * to add color classes and style to the wrapper.
+ */
+ __experimentalSkipSerialization: true,
+ },
+ /**
+ * We need this experimental flag because we don't want to style the
+ * wrapper but inner elements.
+ */
+ __experimentalSelector:
+ '.wc-block-mini-cart__button, .wc-block-mini-cart__badge',
},
example: {
attributes: {
@@ -38,6 +51,10 @@ const settings = {
default: false,
save: false,
},
+ transparentButton: {
+ type: 'boolean',
+ default: true,
+ },
},
edit,
diff --git a/assets/js/blocks/cart-checkout/mini-cart/quantity-badge/index.tsx b/assets/js/blocks/cart-checkout/mini-cart/quantity-badge/index.tsx
index 4cd1825fea6..ac7bfc65c27 100644
--- a/assets/js/blocks/cart-checkout/mini-cart/quantity-badge/index.tsx
+++ b/assets/js/blocks/cart-checkout/mini-cart/quantity-badge/index.tsx
@@ -8,15 +8,32 @@ import { Icon, miniCart } from '@woocommerce/icons';
*/
import './style.scss';
-const QuantityBadge = ( { count }: { count: number } ): JSX.Element => (
-
-
- { count }
-
-);
+interface Props {
+ count: number;
+ colorClassNames?: string;
+ style?: Record< string, string | undefined >;
+}
+
+const QuantityBadge = ( {
+ count,
+ colorClassNames,
+ style,
+}: Props ): JSX.Element => {
+ return (
+
+
+
+ { count }
+
+
+ );
+};
export default QuantityBadge;
diff --git a/assets/js/blocks/cart-checkout/mini-cart/quantity-badge/style.scss b/assets/js/blocks/cart-checkout/mini-cart/quantity-badge/style.scss
index 19654e0ea35..eea3915ad0e 100644
--- a/assets/js/blocks/cart-checkout/mini-cart/quantity-badge/style.scss
+++ b/assets/js/blocks/cart-checkout/mini-cart/quantity-badge/style.scss
@@ -6,9 +6,8 @@
.wc-block-mini-cart__badge {
align-items: center;
background: #fff;
- border: 2px solid;
+ border: 0.15em solid;
border-radius: 1em;
- box-shadow: 0 0 0 2px #fff;
box-sizing: border-box;
color: #000;
display: flex;
diff --git a/assets/js/blocks/cart-checkout/mini-cart/style.scss b/assets/js/blocks/cart-checkout/mini-cart/style.scss
index 1bcb9c01273..e183ce70b0f 100644
--- a/assets/js/blocks/cart-checkout/mini-cart/style.scss
+++ b/assets/js/blocks/cart-checkout/mini-cart/style.scss
@@ -1,18 +1,22 @@
-.wc-block-mini-cart {
+.wc-block-mini-cart.wp-block-woocommerce-mini-cart {
+ background-color: transparent !important;
display: flex;
justify-content: flex-end;
+
+ &.is-transparent .wc-block-mini-cart__button {
+ background-color: transparent !important;
+ }
}
.wc-block-mini-cart__button {
align-items: center;
- background: transparent;
border: none;
+ color: inherit;
display: flex;
font-weight: 400;
padding: em($gap-small) em($gap-smaller);
&:hover {
- background: transparent;
opacity: 0.6;
}
}
@@ -38,6 +42,7 @@
font-size: 1rem;
.components-modal__content {
+ box-sizing: border-box;
display: flex;
flex-direction: column;
height: 100%;
diff --git a/src/BlockTypes/MiniCart.php b/src/BlockTypes/MiniCart.php
index 9794bc9b4f5..6a3b4d3a9f0 100644
--- a/src/BlockTypes/MiniCart.php
+++ b/src/BlockTypes/MiniCart.php
@@ -198,15 +198,17 @@ protected function append_script_and_deps_src( $script ) {
* @return string Rendered block type output.
*/
protected function render( $attributes, $content ) {
- return $content . $this->get_markup();
+ return $content . $this->get_markup( $attributes );
}
/**
* Render the markup for the Mini Cart block.
*
+ * @param array $attributes Block attributes.
+ *
* @return string The HTML markup.
*/
- protected function get_markup() {
+ protected function get_markup( $attributes ) {
if ( is_admin() || WC()->is_rest_api_request() ) {
// In the editor we will display the placeholder, so no need to load
// real cart data and to print the markup.
@@ -222,6 +224,39 @@ protected function get_markup() {
$cart_contents_total += $cart->get_subtotal_tax();
}
+ $wrapper_classes = 'wc-block-mini-cart';
+ $classes = '';
+ $style = '';
+
+ if ( ! isset( $attributes['transparentButton'] ) || $attributes['transparentButton'] ) {
+ $wrapper_classes .= ' is-transparent';
+ }
+
+ /**
+ * Get the color class and inline style.
+ *
+ * @todo refactor the logic of color class and style using StyleAttributesUtils.
+ */
+ if ( ! empty( $attributes['textColor'] ) ) {
+ $classes .= sprintf(
+ ' has-%s-color has-text-color',
+ esc_attr( $attributes['textColor'] )
+ );
+ } elseif ( ! empty( $attributes['style']['color']['text'] ) ) {
+ $style .= 'color: ' . esc_attr( $attributes['style']['color']['text'] ) . ';';
+ $classes .= ' has-text-color';
+ }
+
+ if ( ! empty( $attributes['backgroundColor'] ) ) {
+ $classes .= sprintf(
+ ' has-%s-background-color has-background',
+ esc_attr( $attributes['backgroundColor'] )
+ );
+ } elseif ( ! empty( $attributes['style']['color']['background'] ) ) {
+ $style .= 'background-color: ' . esc_attr( $attributes['style']['color']['background'] ) . ';';
+ $classes .= ' has-background';
+ }
+
$aria_label = sprintf(
/* translators: %1$d is the number of products in the cart. %2$s is the cart total */
_n(
@@ -258,17 +293,17 @@ protected function get_markup() {
$button_html = '' . esc_html( wp_strip_all_tags( wc_price( $cart_contents_total ) ) ) . '
' . $icon . '
- ' . $cart_contents_count . '
+ ' . $cart_contents_count . '
';
if ( is_cart() || is_checkout() ) {
- return '
-
' . $button_html . '
+ return '
+ ' . $button_html . '
';
}
- return '
-
' . $button_html . '
+ return '
+
' . $button_html . '
@@ -335,4 +370,22 @@ protected function get_cart_item_markup() {
';
}
+
+ /**
+ * Get the supports array for this block type.
+ *
+ * @see $this->register_block_type()
+ * @return string;
+ */
+ protected function get_block_type_supports() {
+ return array_merge(
+ parent::get_block_type_supports(),
+ array(
+ 'html' => false,
+ 'multiple' => false,
+ 'color' => true,
+ '__experimentalSelector' => '.wc-block-mini-cart__button, .wc-block-mini-cart__badge',
+ )
+ );
+ }
}