From 04cf1b3b37ee5b138ea69fb6ec1de620ad771c43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Albert=20Juh=C3=A9=20Lluveras?= Date: Thu, 11 May 2023 17:23:36 +0200 Subject: [PATCH] Only show the Mini Cart count badge when there are items in the cart (#9259) * Only show the Mini Cart count badge when there are items in the cart * Update badge to new design * Add tests * Make sure colors don't break existing themes * Update Mini Cart e2e test --- assets/js/blocks/mini-cart/frontend.ts | 35 +++++++++++++++++-- .../blocks/mini-cart/quantity-badge/index.tsx | 4 ++- .../mini-cart/quantity-badge/style.scss | 19 +++++++--- assets/js/blocks/mini-cart/test/block.js | 18 ++++++++++ assets/js/icons/library/mini-cart.tsx | 27 +++++++------- src/BlockTypes/MiniCart.php | 12 ++++--- tests/e2e/specs/shopper/mini-cart.test.js | 2 +- 7 files changed, 91 insertions(+), 26 deletions(-) diff --git a/assets/js/blocks/mini-cart/frontend.ts b/assets/js/blocks/mini-cart/frontend.ts index bd5677f8be8..ea8c4dafdff 100644 --- a/assets/js/blocks/mini-cart/frontend.ts +++ b/assets/js/blocks/mini-cart/frontend.ts @@ -14,6 +14,20 @@ interface dependencyData { translations?: string; } +function getClosestColor( + element: Element | null, + colorType: 'color' | 'backgroundColor' +): string | null { + if ( ! element ) { + return null; + } + const color = window.getComputedStyle( element )[ colorType ]; + if ( color !== 'rgba(0, 0, 0, 0)' && color !== 'transparent' ) { + return color; + } + return getClosestColor( element.parentElement, colorType ); +} + window.addEventListener( 'load', () => { const miniCartBlocks = document.querySelectorAll( '.wc-block-mini-cart' ); let wasLoadScriptsCalled = false; @@ -171,19 +185,34 @@ window.addEventListener( 'load', () => { /** * Get the background color of the body then set it as the background color - * of the Mini-Cart Contents block. We use :where here to make customized - * background color alway have higher priority. + * of the Mini-Cart Contents block. * * We only set the background color, instead of the whole background. As * we only provide the option to customize the background color. */ const style = document.createElement( 'style' ); const backgroundColor = getComputedStyle( document.body ).backgroundColor; - + // For simplicity, we only consider the background color of the first Mini-Cart button. + const firstMiniCartButton = document.querySelector( + '.wc-block-mini-cart__button' + ); + const badgeTextColor = firstMiniCartButton + ? getClosestColor( firstMiniCartButton, 'backgroundColor' ) + : 'inherit'; + const badgeBackgroundColor = firstMiniCartButton + ? getClosestColor( firstMiniCartButton, 'color' ) + : 'inherit'; + + // We use :where here to reduce specificity so customized colors and theme + // CSS take priority. style.appendChild( document.createTextNode( `:where(.wp-block-woocommerce-mini-cart-contents) { background-color: ${ backgroundColor }; + } + :where(.wc-block-mini-cart__badge) { + background-color: ${ badgeBackgroundColor }; + color: ${ badgeTextColor }; }` ) ); diff --git a/assets/js/blocks/mini-cart/quantity-badge/index.tsx b/assets/js/blocks/mini-cart/quantity-badge/index.tsx index 68a4c042398..e69a50f80e7 100644 --- a/assets/js/blocks/mini-cart/quantity-badge/index.tsx +++ b/assets/js/blocks/mini-cart/quantity-badge/index.tsx @@ -22,7 +22,9 @@ const QuantityBadge = ( { count }: Props ): JSX.Element => { size={ 20 } icon={ miniCart } /> - { count } + + { count > 0 ? count : '' } + ); }; diff --git a/assets/js/blocks/mini-cart/quantity-badge/style.scss b/assets/js/blocks/mini-cart/quantity-badge/style.scss index 55afcd37285..35203487961 100644 --- a/assets/js/blocks/mini-cart/quantity-badge/style.scss +++ b/assets/js/blocks/mini-cart/quantity-badge/style.scss @@ -1,28 +1,39 @@ .wc-block-mini-cart__quantity-badge { align-items: center; display: flex; + position: relative; } .wc-block-mini-cart__badge { align-items: center; - background: transparent; - border: 0.15em solid; border-radius: 1em; box-sizing: border-box; - color: inherit; display: flex; font-size: 0.875em; font-weight: 600; height: math.div(em(20px), 0.875); justify-content: center; - margin-left: math.div(em(-10px), 0.875); + left: 100%; + margin-left: -44%; min-width: math.div(em(20px), 0.875); padding: 0 em($gap-smallest); + position: absolute; transform: translateY(-50%); + transition: all 0.15s; white-space: nowrap; z-index: 1; } +:where(.wc-block-mini-cart__badge) { + // These values will be overridden in JS. + background-color: transparent; + color: transparent; +} + +.wc-block-mini-cart__badge:empty { + opacity: 0; +} + .wc-block-mini-cart__icon { display: block; height: em(24px); diff --git a/assets/js/blocks/mini-cart/test/block.js b/assets/js/blocks/mini-cart/test/block.js index 7b298ecc96d..b5b7882d313 100644 --- a/assets/js/blocks/mini-cart/test/block.js +++ b/assets/js/blocks/mini-cart/test/block.js @@ -65,6 +65,24 @@ describe( 'Testing Mini-Cart', () => { fetchMock.resetMocks(); } ); + it( 'shows Mini-Cart count badge when there are items in the cart', async () => { + render( ); + await waitFor( () => expect( fetchMock ).toHaveBeenCalled() ); + + await waitFor( () => + expect( screen.getByText( '3' ) ).toBeInTheDocument() + ); + } ); + + it( "doesn't show Mini-Cart count badge when cart is empty", async () => { + mockEmptyCart(); + render( ); + await waitFor( () => expect( fetchMock ).toHaveBeenCalled() ); + const badgeWith0Count = screen.queryByText( '0' ); + + expect( badgeWith0Count ).toBeNull(); + } ); + it( 'opens Mini-Cart drawer when clicking on button', async () => { render( ); await waitFor( () => expect( fetchMock ).toHaveBeenCalled() ); diff --git a/assets/js/icons/library/mini-cart.tsx b/assets/js/icons/library/mini-cart.tsx index bbf153045c3..7732463dcd1 100644 --- a/assets/js/icons/library/mini-cart.tsx +++ b/assets/js/icons/library/mini-cart.tsx @@ -6,22 +6,25 @@ import { SVG } from '@wordpress/primitives'; const miniCart = ( ); diff --git a/src/BlockTypes/MiniCart.php b/src/BlockTypes/MiniCart.php index d90c165c363..7baaf4d6b09 100644 --- a/src/BlockTypes/MiniCart.php +++ b/src/BlockTypes/MiniCart.php @@ -447,12 +447,14 @@ protected function get_markup( $attributes ) { $cart_contents_count, wp_strip_all_tags( wc_price( $cart_contents_total ) ) ); - $icon = ' - - - + $icon = ' + + + '; - $button_html = $this->get_cart_price_markup( $attributes ) . ' + + $cart_contents_count = $cart_contents_count > 0 ? $cart_contents_count : ''; + $button_html = $this->get_cart_price_markup( $attributes ) . ' ' . $icon . ' ' . $cart_contents_count . ' diff --git a/tests/e2e/specs/shopper/mini-cart.test.js b/tests/e2e/specs/shopper/mini-cart.test.js index e651a100f1c..a8da7b626a3 100644 --- a/tests/e2e/specs/shopper/mini-cart.test.js +++ b/tests/e2e/specs/shopper/mini-cart.test.js @@ -109,7 +109,7 @@ describe( 'Shopper → Mini-Cart', () => { } ); await expect( page ).toMatchElement( '.wc-block-mini-cart__badge', { - text: '0', + text: '', } ); } ); } );