diff --git a/assets/js/base/components/filter-placeholder/index.tsx b/assets/js/base/components/filter-placeholder/index.tsx
index 06a06f92101..679e716ba60 100644
--- a/assets/js/base/components/filter-placeholder/index.tsx
+++ b/assets/js/base/components/filter-placeholder/index.tsx
@@ -1,5 +1,10 @@
+/**
+ * Internal dependencies
+ */
+import './style.scss';
+
interface FilterTitlePlaceholderProps {
- children?: React.ReactChildren;
+ children?: React.ReactNode;
}
const FilterTitlePlaceholder = ( {
diff --git a/assets/js/base/components/filter-placeholder/style.scss b/assets/js/base/components/filter-placeholder/style.scss
index a1a8751ec6a..43ef138eb67 100644
--- a/assets/js/base/components/filter-placeholder/style.scss
+++ b/assets/js/base/components/filter-placeholder/style.scss
@@ -7,7 +7,12 @@
min-width: 80px;
max-width: max-content !important;
- .wc-block-stock-filter__title {
+ &::after {
+ background-image: linear-gradient(90deg, $gray-400, $gray-200, $gray-400);
+ }
+
+ .wc-block-stock-filter__title,
+ .wc-block-price-filter__title {
margin: 0;
height: 1em;
}
diff --git a/assets/js/base/components/price-slider/index.tsx b/assets/js/base/components/price-slider/index.tsx
index d9f2faa0704..e359a2817c0 100644
--- a/assets/js/base/components/price-slider/index.tsx
+++ b/assets/js/base/components/price-slider/index.tsx
@@ -33,6 +33,10 @@ export interface PriceSliderProps {
* Whether values are loading or not.
*/
isLoading?: boolean;
+ /**
+ * Whether values are updating or not. The update starts when the price slider is changed.
+ */
+ isUpdating?: boolean;
/**
* Maximum constraint.
*/
@@ -87,6 +91,7 @@ const PriceSlider = ( {
showFilterButton = false,
inlineInput = true,
isLoading = false,
+ isUpdating = false,
onSubmit = () => void 0,
}: PriceSliderProps ): JSX.Element => {
const minRange = useRef< HTMLInputElement >( null );
@@ -301,7 +306,6 @@ const PriceSlider = ( {
showFilterButton && 'wc-block-price-filter--has-filter-button',
showFilterButton &&
'wc-block-components-price-slider--has-filter-button',
- isLoading && 'is-loading',
! hasValidConstraints && 'is-disabled',
( inlineInput || wrapperWidth <= 300 ) &&
'wc-block-components-price-slider--is-input-inline'
@@ -326,7 +330,11 @@ const PriceSlider = ( {
const slider = (
@@ -388,58 +396,68 @@ const PriceSlider = ( {
{ ( ! inlineInputAvailable || ! showInputFields ) && slider }
{ showInputFields && (
-
{
- if ( value === minPriceInput ) {
- return;
- }
- setMinPriceInput( value );
- } }
- onBlur={ priceInputOnBlur }
- disabled={ isLoading || ! hasValidConstraints }
- value={ minPriceInput }
- />
+ { ! isUpdating ? (
+ {
+ if ( value === minPriceInput ) {
+ return;
+ }
+ setMinPriceInput( value );
+ } }
+ onBlur={ priceInputOnBlur }
+ disabled={ isLoading || ! hasValidConstraints }
+ value={ minPriceInput }
+ />
+ ) : (
+
+ ) }
{ inlineInputAvailable && slider }
- {
- if ( value === maxPriceInput ) {
- return;
- }
- setMaxPriceInput( value );
- } }
- onBlur={ priceInputOnBlur }
- disabled={ isLoading || ! hasValidConstraints }
- value={ maxPriceInput }
- />
+ { ! isUpdating ? (
+ {
+ if ( value === maxPriceInput ) {
+ return;
+ }
+ setMaxPriceInput( value );
+ } }
+ onBlur={ priceInputOnBlur }
+ disabled={ isLoading || ! hasValidConstraints }
+ value={ maxPriceInput }
+ />
+ ) : (
+
+ ) }
) }
{ ! showInputFields &&
- ! isLoading &&
+ ! isUpdating &&
Number.isFinite( minPrice ) &&
Number.isFinite( maxPrice ) && (
@@ -453,32 +471,34 @@ const PriceSlider = ( {
/>
) }
-
- { ( minPrice !== minConstraint ||
- maxPrice !== maxConstraint ) && (
- {
- onChange( [ minConstraint, maxConstraint ] );
- debouncedUpdateQuery();
- } }
- screenReaderLabel={ __(
- 'Reset price filter',
- 'woo-gutenberg-products-block'
- ) }
- />
- ) }
- { showFilterButton && (
-
- ) }
-
+ { ! isUpdating && (
+
+ { ( minPrice !== minConstraint ||
+ maxPrice !== maxConstraint ) && (
+ {
+ onChange( [ minConstraint, maxConstraint ] );
+ debouncedUpdateQuery();
+ } }
+ screenReaderLabel={ __(
+ 'Reset price filter',
+ 'woo-gutenberg-products-block'
+ ) }
+ />
+ ) }
+ { showFilterButton && (
+
+ ) }
+
+ ) }
);
};
diff --git a/assets/js/base/components/price-slider/style.scss b/assets/js/base/components/price-slider/style.scss
index b894c810a9d..a445c12f902 100644
--- a/assets/js/base/components/price-slider/style.scss
+++ b/assets/js/base/components/price-slider/style.scss
@@ -83,6 +83,12 @@
height: 4px;
margin: 15px 0;
position: relative;
+
+ &.is-loading {
+ @include placeholder();
+ height: em(9px);
+ border-radius: 0;
+ }
}
.wc-block-components-price-slider__range-input-progress {
@@ -116,6 +122,12 @@
.wc-block-components-price-slider--is-input-inline & {
max-width: 60px;
}
+
+ &.is-loading {
+ @include placeholder();
+ border-radius: 0 !important;
+ width: max-content;
+ }
}
}
diff --git a/assets/js/blocks/price-filter/block.tsx b/assets/js/blocks/price-filter/block.tsx
index 87c5df5cb2d..4e191b55658 100644
--- a/assets/js/blocks/price-filter/block.tsx
+++ b/assets/js/blocks/price-filter/block.tsx
@@ -9,6 +9,7 @@ import {
} from '@woocommerce/base-context/hooks';
import { useCallback, useState, useEffect } from '@wordpress/element';
import PriceSlider from '@woocommerce/base-components/price-slider';
+import FilterTitlePlaceholder from '@woocommerce/base-components/filter-placeholder';
import { useDebouncedCallback } from 'use-debounce';
import PropTypes from 'prop-types';
import { getCurrencyFromPriceResponse } from '@woocommerce/price-format';
@@ -164,6 +165,8 @@ const PriceFilterBlock = ( {
setMinPriceQuery,
] );
+ const [ isUpdating, setIsUpdating ] = useState( isLoading );
+
// Updates the query based on slider values.
const onSubmit = useCallback(
( newMinPrice, newMaxPrice ) => {
@@ -206,6 +209,7 @@ const PriceFilterBlock = ( {
// Callback when slider or input fields are changed.
const onChange = useCallback(
( prices ) => {
+ setIsUpdating( true );
if ( prices[ 0 ] !== minPrice ) {
setMinPrice( prices[ 0 ] );
}
@@ -303,13 +307,26 @@ const PriceFilterBlock = ( {
const TagName =
`h${ attributes.headingLevel }` as keyof JSX.IntrinsicElements;
+ if ( ! isLoading && isUpdating ) {
+ setIsUpdating( false );
+ }
+
+ const heading = (
+
+ { attributes.heading }
+
+ );
+
+ const filterHeading =
+ isLoading && isUpdating ? (
+ { heading }
+ ) : (
+ heading
+ );
+
return (
<>
- { ! isEditor && attributes.heading && (
-
- { attributes.heading }
-
- ) }
+ { ! isEditor && attributes.heading && filterHeading }
onSubmit( minPrice, maxPrice ) }
isLoading={ isLoading }
+ isUpdating={ isUpdating }
/>
>
diff --git a/assets/js/blocks/price-filter/style.scss b/assets/js/blocks/price-filter/style.scss
index c67de60650f..1aa0bc92f67 100644
--- a/assets/js/blocks/price-filter/style.scss
+++ b/assets/js/blocks/price-filter/style.scss
@@ -23,17 +23,23 @@
border-color: inherit;
}
-
.wc-block-price-filter__controls {
border-radius: inherit;
border-color: inherit;
- // Force inherting style is required for global style.
+ // Force inheriting style is required for global style.
input {
border-radius: inherit !important;
border-color: inherit !important;
border-style: solid;
}
+
+ .input-loading {
+ @include placeholder();
+ border-radius: 0;
+ height: em(32px);
+ width: em(90px);
+ }
}
.editor-styles-wrapper .wc-block-price-filter__button.wc-block-components-price-slider__button,