diff --git a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/product-price/index.js b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/product-price/index.js index 9b05ce58943..85e64c16529 100644 --- a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/product-price/index.js +++ b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/product-price/index.js @@ -1,6 +1,7 @@ /** * External dependencies */ +import { __ } from '@wordpress/i18n'; import FormattedMonetaryAmount from '@woocommerce/base-components/formatted-monetary-amount'; import classNames from 'classnames'; import PropTypes from 'prop-types'; @@ -11,20 +12,38 @@ import PropTypes from 'prop-types'; import './style.scss'; const ProductPrice = ( { className, currency, regularValue, value } ) => { + const isDiscounted = + Number.isFinite( regularValue ) && regularValue !== value; return ( <> - { Number.isFinite( regularValue ) && regularValue !== value && ( - + { isDiscounted && ( + <> + + { __( + 'Previous price:', + 'woo-gutenberg-products-block' + ) } + + + + { __( + 'Discounted price:', + 'woo-gutenberg-products-block' + ) } + + ) } diff --git a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/product-price/style.scss b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/product-price/style.scss index cf5e5e3d8d4..4e5871fc365 100644 --- a/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/product-price/style.scss +++ b/plugins/woocommerce-blocks/assets/js/base/components/cart-checkout/product-price/style.scss @@ -1,12 +1,12 @@ .wc-block-product-price { color: $black; + + &.is-discounted { + margin-left: 0.5em; + } } .wc-block-product-price--regular { color: $core-grey-dark-400; text-decoration: line-through; - - + .wc-block-product-price { - margin-left: 0.5em; - } } diff --git a/plugins/woocommerce-blocks/assets/js/base/components/checkout/form-step/style.scss b/plugins/woocommerce-blocks/assets/js/base/components/checkout/form-step/style.scss index c6c0b89c6de..2130303261b 100644 --- a/plugins/woocommerce-blocks/assets/js/base/components/checkout/form-step/style.scss +++ b/plugins/woocommerce-blocks/assets/js/base/components/checkout/form-step/style.scss @@ -11,10 +11,6 @@ $line-offset-from-circle-size: 8px; padding: 0 $gap-larger $gap-larger $gap-larger; background: none; margin: 0; - - &:last-child::before { - content: none; - } } .wc-block-checkout-step__heading { @@ -54,20 +50,7 @@ $line-offset-from-circle-size: 8px; margin-bottom: $gap-large; } -// because themes can register different background colors, we can't always -// relay on using white border to offest the step left line, .wc-block-checkout-step::before { - content: ""; - // 1 Circle size + offset of the first circle and next circle. - height: calc(100% - #{$circle-size + $line-offset-from-circle-size * 2}); - width: 1px; - background-color: $gray-10; - position: absolute; - left: $circle-size/2; - top: $circle-size + $line-offset-from-circle-size; -} - -.wc-block-checkout-step::after { counter-increment: checkout-step; content: counter(checkout-step); position: absolute; @@ -83,3 +66,20 @@ $line-offset-from-circle-size: 8px; border-radius: $circle-size / 2; box-sizing: content-box; } + +// because themes can register different background colors, we can't always +// relay on using white border to offest the step left line, +.wc-block-checkout-step::after { + content: ""; + // 1 Circle size + offset of the first circle and next circle. + height: calc(100% - #{$circle-size + $line-offset-from-circle-size * 2}); + width: 1px; + background-color: $gray-10; + position: absolute; + left: $circle-size/2; + top: $circle-size + $line-offset-from-circle-size; +} + +.wc-block-checkout-step:last-child::after { + content: none; +} diff --git a/plugins/woocommerce-blocks/assets/js/base/components/shipping-rates-control/index.js b/plugins/woocommerce-blocks/assets/js/base/components/shipping-rates-control/index.js index 3072a5a0fef..ec7d8709c3f 100644 --- a/plugins/woocommerce-blocks/assets/js/base/components/shipping-rates-control/index.js +++ b/plugins/woocommerce-blocks/assets/js/base/components/shipping-rates-control/index.js @@ -1,8 +1,10 @@ /** * External dependencies */ -import { __ } from '@wordpress/i18n'; +import { __, _n, sprintf } from '@wordpress/i18n'; +import { useEffect } from 'react'; import PropTypes from 'prop-types'; +import { speak } from '@wordpress/a11y'; /** * Internal dependencies @@ -19,6 +21,62 @@ const ShippingRatesControl = ( { noResultsMessage, renderOption, } ) => { + useEffect( () => { + if ( shippingRatesLoading ) { + return; + } + const packages = shippingRates.length; + const shippingOptions = shippingRates.reduce( + ( acc, shippingRate ) => acc + shippingRate.shipping_rates.length, + 0 + ); + if ( shippingOptions === 0 ) { + speak( + __( + 'No shipping options were found.', + 'woo-gutenberg-products-block' + ) + ); + } else if ( packages === 1 ) { + speak( + sprintf( + // translators: %d number of shipping options found. + _n( + '%d shipping option was found.', + '%d shipping options were found.', + shippingOptions, + 'woo-gutenberg-products-block' + ), + shippingOptions + ) + ); + } else { + speak( + sprintf( + // translators: %d number of shipping packages packages. + _n( + 'Shipping option searched for %d package.', + 'Shipping options searched for %d packages.', + packages, + 'woo-gutenberg-products-block' + ), + packages + ) + + ' ' + + sprintf( + // translators: %d number of shipping options available. + _n( + '%d shipping option was found', + '%d shipping options were found', + shippingOptions, + 'woo-gutenberg-products-block' + ), + shippingOptions + ) + ); + } + }, [ shippingRatesLoading, shippingRates ] ); + return ( { ! isCheckout && showingRates && ( diff --git a/plugins/woocommerce-blocks/assets/js/base/components/totals/totals-shipping-item/shipping-rate-selector.js b/plugins/woocommerce-blocks/assets/js/base/components/totals/totals-shipping-item/shipping-rate-selector.js index 2c745b1a6df..e9ec0860f48 100644 --- a/plugins/woocommerce-blocks/assets/js/base/components/totals/totals-shipping-item/shipping-rate-selector.js +++ b/plugins/woocommerce-blocks/assets/js/base/components/totals/totals-shipping-item/shipping-rate-selector.js @@ -24,14 +24,20 @@ const renderShippingRatesControlOption = ( option ) => ( { ), } ); -const ShippingRateSelector = ( { shippingRates, shippingRatesLoading } ) => { +const ShippingRateSelector = ( { + hasRates, + shippingRates, + shippingRatesLoading, +} ) => { return (
- { __( - 'Choose a shipping method', - 'woo-gutenberg-products-block' - ) } + { hasRates + ? __( 'Shipping methods', 'woo-gutenberg-products-block' ) + : __( + 'Choose a shipping method', + 'woo-gutenberg-products-block' + ) } { * Provides an id for the validation error that can be used to fill out * aria-describedby attribute values. * - * @param {string} inputId The input css id the validation error is related + * @param {string} errorId The input css id the validation error is related * to. * @return {string} The id to use for the validation error container. */ - const getValidationErrorId = ( inputId ) => { - return inputId ? `validate-error-${ inputId }` : ''; + const getValidationErrorId = ( errorId ) => { + const error = getValidationError( errorId ); + if ( ! error || error.hidden ) { + return ''; + } + return `validate-error-${ errorId }`; }; const context = { diff --git a/plugins/woocommerce-blocks/assets/js/blocks/cart-checkout/cart/full-cart/cart-line-item-row.js b/plugins/woocommerce-blocks/assets/js/blocks/cart-checkout/cart/full-cart/cart-line-item-row.js index 1ea504f2773..20d9b3db90e 100644 --- a/plugins/woocommerce-blocks/assets/js/blocks/cart-checkout/cart/full-cart/cart-line-item-row.js +++ b/plugins/woocommerce-blocks/assets/js/blocks/cart-checkout/cart/full-cart/cart-line-item-row.js @@ -99,12 +99,18 @@ const CartLineItemRow = ( { lineItem } ) => { precision: parseInt( prices.raw_prices.precision, 10 ), } ).multiply( quantity ); const saleAmount = regularAmount.subtract( purchaseAmount ); + const firstImage = images.length ? images[ 0 ] : {}; return ( - - - + { /* If the image has no alt text, this link is unnecessary and can be hidden. */ } + + { /* We don't need to make it focusable, because product name has the same link. */ } + + diff --git a/plugins/woocommerce-blocks/assets/js/blocks/cart-checkout/checkout/block.js b/plugins/woocommerce-blocks/assets/js/blocks/cart-checkout/checkout/block.js index ccbb7d39b67..71fab54fdd7 100644 --- a/plugins/woocommerce-blocks/assets/js/blocks/cart-checkout/checkout/block.js +++ b/plugins/woocommerce-blocks/assets/js/blocks/cart-checkout/checkout/block.js @@ -129,211 +129,227 @@ const Checkout = ( { } }, [ shippingAsBilling, setBillingData ] ); return ( - -
- - - ( - - { __( - 'Already have an account? ', - 'woo-gutenberg-products-block' - ) } - - { __( - 'Log in.', - 'woo-gutenberg-products-block' - ) } - - - ) } - > - - setBillingData( { email: newValue } ) - } - required={ true } - /> - - setContactFields( { - ...contactFields, - keepUpdated: ! contactFields.keepUpdated, - } ) - } - /> - - { SHIPPING_ENABLED && ( + <> + +
+ + ( + + { __( + 'Already have an account? ', + 'woo-gutenberg-products-block' + ) } + + { __( + 'Log in.', + 'woo-gutenberg-products-block' + ) } + + + ) } > - + setBillingData( { email: newValue } ) + } + required={ true } /> - { attributes.showPhoneField && ( - - setBillingData( { phone: newValue } ) + + setContactFields( { + ...contactFields, + keepUpdated: ! contactFields.keepUpdated, + } ) + } + /> + + { SHIPPING_ENABLED && ( + + + { attributes.showPhoneField && ( + + setBillingData( { + phone: newValue, + } ) + } + required={ + attributes.requirePhoneField + } + /> + ) } + + setShippingAsBilling( isChecked ) } required={ attributes.requirePhoneField } /> - ) } - + ) } + { showBillingFields && ( + - setShippingAsBilling( isChecked ) - } - required={ attributes.requirePhoneField } - /> - - ) } - { showBillingFields && ( - - - - ) } - { SHIPPING_ENABLED && ( - - { shippingRates.length === 0 && isEditor ? ( - - ) : ( - + + + ) } + { SHIPPING_ENABLED && ( + + { shippingRates.length === 0 && isEditor ? ( + + ) : ( + + ) } + { /*@todo This is not implemented*/ } + null } + /> + + ) } + null } - /> + description={ __( + 'Select a payment method below.', + 'woo-gutenberg-products-block' + ) } + > + - ) } - - - + +
+ + + +
{ attributes.showReturnToCart && (
{ attributes.showPolicyLinks && } - -
- - - -
+
+
+ ); }; diff --git a/plugins/woocommerce-blocks/assets/js/blocks/cart-checkout/checkout/sidebar/order-summary-item.js b/plugins/woocommerce-blocks/assets/js/blocks/cart-checkout/checkout/sidebar/order-summary-item.js index 763908f9758..0afa8f42194 100644 --- a/plugins/woocommerce-blocks/assets/js/blocks/cart-checkout/checkout/sidebar/order-summary-item.js +++ b/plugins/woocommerce-blocks/assets/js/blocks/cart-checkout/checkout/sidebar/order-summary-item.js @@ -54,12 +54,12 @@ const CheckoutOrderSummaryItem = ( { cartItem } ) => {
+ -