Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Commit

Permalink
Update filter by price skeleton design (#6997)
Browse files Browse the repository at this point in the history
* Update filter by price skeleton design

* Improve skeleton colors

* Update skeleton when no apply button

* Update skeleton with apply button

* Avoid showing a very wide placeholder when the filter title is very long

* Start using the FilterTitlePlaceholder component for the placeholder

* Add comment to isUpdating

* Remove unneeded styles

* Fix title animation
  • Loading branch information
albarin authored Sep 2, 2022
1 parent 386d7e0 commit 824a92f
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 84 deletions.
7 changes: 6 additions & 1 deletion assets/js/base/components/filter-placeholder/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
/**
* Internal dependencies
*/
import './style.scss';

interface FilterTitlePlaceholderProps {
children?: React.ReactChildren;
children?: React.ReactNode;
}

const FilterTitlePlaceholder = ( {
Expand Down
7 changes: 6 additions & 1 deletion assets/js/base/components/filter-placeholder/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
170 changes: 95 additions & 75 deletions assets/js/base/components/price-slider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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 );
Expand Down Expand Up @@ -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'
Expand All @@ -326,7 +330,11 @@ const PriceSlider = ( {

const slider = (
<div
className="wc-block-price-filter__range-input-wrapper wc-block-components-price-slider__range-input-wrapper"
className={ classnames(
'wc-block-price-filter__range-input-wrapper',
'wc-block-components-price-slider__range-input-wrapper',
{ 'is-loading': isLoading && isUpdating }
) }
onMouseMove={ findClosestRange }
onFocus={ findClosestRange }
>
Expand Down Expand Up @@ -388,58 +396,68 @@ const PriceSlider = ( {
{ ( ! inlineInputAvailable || ! showInputFields ) && slider }
{ showInputFields && (
<div className="wc-block-price-filter__controls wc-block-components-price-slider__controls">
<FormattedMonetaryAmount
currency={ currency }
displayType="input"
className="wc-block-price-filter__amount wc-block-price-filter__amount--min wc-block-form-text-input wc-block-components-price-slider__amount wc-block-components-price-slider__amount--min"
aria-label={ __(
'Filter products by minimum price',
'woo-gutenberg-products-block'
) }
allowNegative={ false }
isAllowed={ isValidMinValue( {
minConstraint,
minorUnit: currency.minorUnit,
currentMaxValue: maxPriceInput,
} ) }
onValueChange={ ( value ) => {
if ( value === minPriceInput ) {
return;
}
setMinPriceInput( value );
} }
onBlur={ priceInputOnBlur }
disabled={ isLoading || ! hasValidConstraints }
value={ minPriceInput }
/>
{ ! isUpdating ? (
<FormattedMonetaryAmount
currency={ currency }
displayType="input"
className="wc-block-price-filter__amount wc-block-price-filter__amount--min wc-block-form-text-input wc-block-components-price-slider__amount wc-block-components-price-slider__amount--min"
aria-label={ __(
'Filter products by minimum price',
'woo-gutenberg-products-block'
) }
allowNegative={ false }
isLoading={ isLoading }
isAllowed={ isValidMinValue( {
minConstraint,
minorUnit: currency.minorUnit,
currentMaxValue: maxPriceInput,
} ) }
onValueChange={ ( value ) => {
if ( value === minPriceInput ) {
return;
}
setMinPriceInput( value );
} }
onBlur={ priceInputOnBlur }
disabled={ isLoading || ! hasValidConstraints }
value={ minPriceInput }
/>
) : (
<div className="input-loading"></div>
) }
{ inlineInputAvailable && slider }
<FormattedMonetaryAmount
currency={ currency }
displayType="input"
className="wc-block-price-filter__amount wc-block-price-filter__amount--max wc-block-form-text-input wc-block-components-price-slider__amount wc-block-components-price-slider__amount--max"
aria-label={ __(
'Filter products by maximum price',
'woo-gutenberg-products-block'
) }
isAllowed={ isValidMaxValue( {
maxConstraint,
minorUnit: currency.minorUnit,
} ) }
onValueChange={ ( value ) => {
if ( value === maxPriceInput ) {
return;
}
setMaxPriceInput( value );
} }
onBlur={ priceInputOnBlur }
disabled={ isLoading || ! hasValidConstraints }
value={ maxPriceInput }
/>
{ ! isUpdating ? (
<FormattedMonetaryAmount
currency={ currency }
displayType="input"
className="wc-block-price-filter__amount wc-block-price-filter__amount--max wc-block-form-text-input wc-block-components-price-slider__amount wc-block-components-price-slider__amount--max"
aria-label={ __(
'Filter products by maximum price',
'woo-gutenberg-products-block'
) }
isLoading={ isLoading }
isAllowed={ isValidMaxValue( {
maxConstraint,
minorUnit: currency.minorUnit,
} ) }
onValueChange={ ( value ) => {
if ( value === maxPriceInput ) {
return;
}
setMaxPriceInput( value );
} }
onBlur={ priceInputOnBlur }
disabled={ isLoading || ! hasValidConstraints }
value={ maxPriceInput }
/>
) : (
<div className="input-loading"></div>
) }
</div>
) }

{ ! showInputFields &&
! isLoading &&
! isUpdating &&
Number.isFinite( minPrice ) &&
Number.isFinite( maxPrice ) && (
<div className="wc-block-price-filter__range-text wc-block-components-price-slider__range-text">
Expand All @@ -453,32 +471,34 @@ const PriceSlider = ( {
/>
</div>
) }
<div className="wc-block-components-price-slider__actions">
{ ( minPrice !== minConstraint ||
maxPrice !== maxConstraint ) && (
<FilterResetButton
onClick={ () => {
onChange( [ minConstraint, maxConstraint ] );
debouncedUpdateQuery();
} }
screenReaderLabel={ __(
'Reset price filter',
'woo-gutenberg-products-block'
) }
/>
) }
{ showFilterButton && (
<FilterSubmitButton
className="wc-block-price-filter__button wc-block-components-price-slider__button"
disabled={ isLoading || ! hasValidConstraints }
onClick={ onSubmit }
screenReaderLabel={ __(
'Apply price filter',
'woo-gutenberg-products-block'
) }
/>
) }
</div>
{ ! isUpdating && (
<div className="wc-block-components-price-slider__actions">
{ ( minPrice !== minConstraint ||
maxPrice !== maxConstraint ) && (
<FilterResetButton
onClick={ () => {
onChange( [ minConstraint, maxConstraint ] );
debouncedUpdateQuery();
} }
screenReaderLabel={ __(
'Reset price filter',
'woo-gutenberg-products-block'
) }
/>
) }
{ showFilterButton && (
<FilterSubmitButton
className="wc-block-price-filter__button wc-block-components-price-slider__button"
disabled={ isLoading || ! hasValidConstraints }
onClick={ onSubmit }
screenReaderLabel={ __(
'Apply price filter',
'woo-gutenberg-products-block'
) }
/>
) }
</div>
) }
</div>
);
};
Expand Down
12 changes: 12 additions & 0 deletions assets/js/base/components/price-slider/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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;
}
}
}

Expand Down
28 changes: 23 additions & 5 deletions assets/js/blocks/price-filter/block.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -164,6 +165,8 @@ const PriceFilterBlock = ( {
setMinPriceQuery,
] );

const [ isUpdating, setIsUpdating ] = useState( isLoading );

// Updates the query based on slider values.
const onSubmit = useCallback(
( newMinPrice, newMaxPrice ) => {
Expand Down Expand Up @@ -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 ] );
}
Expand Down Expand Up @@ -303,13 +307,26 @@ const PriceFilterBlock = ( {
const TagName =
`h${ attributes.headingLevel }` as keyof JSX.IntrinsicElements;

if ( ! isLoading && isUpdating ) {
setIsUpdating( false );
}

const heading = (
<TagName className="wc-block-price-filter__title">
{ attributes.heading }
</TagName>
);

const filterHeading =
isLoading && isUpdating ? (
<FilterTitlePlaceholder>{ heading }</FilterTitlePlaceholder>
) : (
heading
);

return (
<>
{ ! isEditor && attributes.heading && (
<TagName className="wc-block-price-filter__title">
{ attributes.heading }
</TagName>
) }
{ ! isEditor && attributes.heading && filterHeading }
<div className="wc-block-price-slider">
<PriceSlider
minConstraint={ minConstraint }
Expand All @@ -323,6 +340,7 @@ const PriceFilterBlock = ( {
onChange={ onChange }
onSubmit={ () => onSubmit( minPrice, maxPrice ) }
isLoading={ isLoading }
isUpdating={ isUpdating }
/>
</div>
</>
Expand Down
10 changes: 8 additions & 2 deletions assets/js/blocks/price-filter/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down

0 comments on commit 824a92f

Please sign in to comment.