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

Price Filter Block Design update #6877

Merged
merged 36 commits into from
Aug 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
c34eb7a
make toggle control full width
dinhtungdu Aug 9, 2022
2bb8c34
add inlineInput attribute
dinhtungdu Aug 9, 2022
d90037c
add inlineInput sidebar setting
dinhtungdu Aug 9, 2022
97edad9
add inlineInput help text
dinhtungdu Aug 9, 2022
8e7d426
style the filter button
dinhtungdu Aug 9, 2022
66ba8f4
style price input
dinhtungdu Aug 9, 2022
5eeb706
wip: reset button
dinhtungdu Aug 9, 2022
f6fca92
clicking on reset button will reset the price query
dinhtungdu Aug 10, 2022
ee308b3
support inline input fields
dinhtungdu Aug 10, 2022
eb6d8fc
price text styling update
dinhtungdu Aug 10, 2022
45d357d
fix reset button font size
dinhtungdu Aug 10, 2022
eae7069
add loading placeholder to all elements
dinhtungdu Aug 10, 2022
e84b219
fix filter button style
dinhtungdu Aug 10, 2022
ead9dea
update range slider thumb and track style
dinhtungdu Aug 10, 2022
de08346
fix loading placeholder for non empty query
dinhtungdu Aug 10, 2022
dee7dc6
move reset button into FilterSubmitButton component
dinhtungdu Aug 10, 2022
98f08ef
try: render placeholder serverside
dinhtungdu Aug 11, 2022
b41f15d
update filter button label
dinhtungdu Aug 11, 2022
7b4d9f1
Revert "try: render placeholder serverside"
dinhtungdu Aug 11, 2022
36559ed
remove LoadingPlaceholder component
dinhtungdu Aug 11, 2022
b348935
remove Price: prefix from the current displayed price range
dinhtungdu Aug 11, 2022
2484b2d
update labels
dinhtungdu Aug 12, 2022
4868acb
extract reset button as a dedicated component
dinhtungdu Aug 12, 2022
edb749f
update price text section
dinhtungdu Aug 12, 2022
42d2b82
update reset button behavior
dinhtungdu Aug 12, 2022
d291e8c
avoid breaking filter submit button style for other filter blocks
dinhtungdu Aug 12, 2022
5f29d5a
rename block to Filter by Price
dinhtungdu Aug 12, 2022
bc185d3
fix e2e test
dinhtungdu Aug 12, 2022
79fa2ea
remove border support
dinhtungdu Aug 15, 2022
61e3b37
adjust padding for elments
dinhtungdu Aug 15, 2022
4972bc8
rename panel title
dinhtungdu Aug 15, 2022
7671e4b
Merge branch 'trunk' into fix/6841
dinhtungdu Aug 15, 2022
28b4193
Make the inline option enabled by default and fix frontend rendering
albarin Aug 16, 2022
e462a03
Make the `Price Range Selector` uppercase
albarin Aug 16, 2022
fa041dd
Show `Reset` button only when a selection has been made
albarin Aug 16, 2022
12b4251
Revert the `save` change to avoid the 'Block Recovery Prompt'
albarin Aug 16, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions assets/js/base/components/filter-reset-button/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* External dependencies
*/
import { __ } from '@wordpress/i18n';
import classNames from 'classnames';
import Label from '@woocommerce/base-components/label';

/**
* Internal dependencies
*/
import './style.scss';

interface FilterResetButtonProps {
className?: string;
label?: string;
onClick: () => void;
screenReaderLabel?: string;
}

const FilterResetButton = ( {
className,
/* translators: Reset button text for filters. */
label = __( 'Reset', 'woo-gutenberg-products-block' ),
onClick,
screenReaderLabel = __( 'Reset filter', 'woo-gutenberg-products-block' ),
}: FilterResetButtonProps ): JSX.Element => {
return (
<button
className={ classNames(
'wc-block-components-filter-reset-button',
className
) }
onClick={ onClick }
>
<Label label={ label } screenReaderLabel={ screenReaderLabel } />
</button>
);
};

export default FilterResetButton;
14 changes: 14 additions & 0 deletions assets/js/base/components/filter-reset-button/style.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.wc-block-components-filter-reset-button {
background: transparent;
border: none;
cursor: pointer;
font-size: inherit;

&:not([disabled]):hover {
text-decoration: underline;
}

&[disabled] {
cursor: not-allowed;
}
}
3 changes: 2 additions & 1 deletion assets/js/base/components/filter-submit-button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,15 @@ const FilterSubmitButton = ( {
className,
disabled,
/* translators: Submit button text for filters. */
label = __( 'Go', 'woo-gutenberg-products-block' ),
label = __( 'Apply', 'woo-gutenberg-products-block' ),
onClick,
screenReaderLabel = __( 'Apply filter', 'woo-gutenberg-products-block' ),
}: FilterSubmitButtonProps ): JSX.Element => {
return (
<button
type="submit"
className={ classNames(
'wp-block-button__link',
'wc-block-filter-submit-button',
'wc-block-components-filter-submit-button',
className
Expand Down
1 change: 1 addition & 0 deletions assets/js/base/components/filter-submit-button/style.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.wc-block-components-filter-submit-button {
border: none;
display: block;
margin-left: auto;
white-space: nowrap;
Expand Down
257 changes: 141 additions & 116 deletions assets/js/base/components/price-slider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
import classnames from 'classnames';
import FormattedMonetaryAmount from '@woocommerce/base-components/formatted-monetary-amount';
import { Currency, isObject } from '@woocommerce/types';
import { useDebouncedCallback } from 'use-debounce';

/**
* Internal dependencies
Expand All @@ -20,6 +21,7 @@ import './style.scss';
import { constrainRangeSliderValues } from './constrain-range-slider-values';
import FilterSubmitButton from '../filter-submit-button';
import { isValidMaxValue, isValidMinValue } from './utils';
import FilterResetButton from '../filter-reset-button';

export interface PriceSliderProps {
/**
Expand Down Expand Up @@ -62,6 +64,10 @@ export interface PriceSliderProps {
* Whether to show input fields for the values or not.
*/
showInputFields?: boolean;
/**
* Whether to show input fields inline with the slider or not.
*/
inlineInput?: boolean;
/**
* What step values the slider uses.
*/
Expand All @@ -78,6 +84,7 @@ const PriceSlider = ( {
currency,
showInputFields = true,
showFilterButton = false,
inlineInput = true,
isLoading = false,
onSubmit = () => void 0,
}: PriceSliderProps ): JSX.Element => {
Expand Down Expand Up @@ -274,6 +281,8 @@ const PriceSlider = ( {
[ onChange, stepValue, minPriceInput, maxPriceInput ]
);

const debouncedUpdateQuery = useDebouncedCallback( onSubmit, 600 );

const classes = classnames(
'wc-block-price-filter',
'wc-block-components-price-slider',
Expand Down Expand Up @@ -301,133 +310,149 @@ const PriceSlider = ( {
maxPriceInput / 10 ** currency.minorUnit
);

const slider = (
<div
className="wc-block-price-filter__range-input-wrapper wc-block-components-price-slider__range-input-wrapper"
onMouseMove={ findClosestRange }
onFocus={ findClosestRange }
>
{ hasValidConstraints && (
<div aria-hidden={ showInputFields }>
<div
className="wc-block-price-filter__range-input-progress wc-block-components-price-slider__range-input-progress"
style={ progressStyles as React.CSSProperties }
/>
<input
type="range"
className="wc-block-price-filter__range-input wc-block-price-filter__range-input--min wc-block-components-price-slider__range-input wc-block-components-price-slider__range-input--min"
aria-label={ __(
'Filter products by minimum price',
'woo-gutenberg-products-block'
) }
aria-valuetext={ ariaReadableMinPrice }
value={
Number.isFinite( minPrice )
? minPrice
: minConstraint
}
onChange={ rangeInputOnChange }
step={ minRangeStep }
min={ minConstraint }
max={ maxConstraint }
ref={ minRange }
disabled={ isLoading && ! hasValidConstraints }
tabIndex={ showInputFields ? -1 : 0 }
/>
<input
type="range"
className="wc-block-price-filter__range-input wc-block-price-filter__range-input--max wc-block-components-price-slider__range-input wc-block-components-price-slider__range-input--max"
aria-label={ __(
'Filter products by maximum price',
'woo-gutenberg-products-block'
) }
aria-valuetext={ ariaReadableMaxPrice }
value={
Number.isFinite( maxPrice )
? maxPrice
: maxConstraint
}
onChange={ rangeInputOnChange }
step={ maxRangeStep }
min={ minConstraint }
max={ maxConstraint }
ref={ maxRange }
disabled={ isLoading }
tabIndex={ showInputFields ? -1 : 0 }
/>
</div>
) }
</div>
);

return (
<div className={ classes }>
<div
className="wc-block-price-filter__range-input-wrapper wc-block-components-price-slider__range-input-wrapper"
onMouseMove={ findClosestRange }
onFocus={ findClosestRange }
>
{ hasValidConstraints && (
<div aria-hidden={ showInputFields }>
<div
className="wc-block-price-filter__range-input-progress wc-block-components-price-slider__range-input-progress"
style={ progressStyles as React.CSSProperties }
/>
<input
type="range"
className="wc-block-price-filter__range-input wc-block-price-filter__range-input--min wc-block-components-price-slider__range-input wc-block-components-price-slider__range-input--min"
aria-label={ __(
'Filter products by minimum price',
'woo-gutenberg-products-block'
) }
aria-valuetext={ ariaReadableMinPrice }
value={
Number.isFinite( minPrice )
? minPrice
: minConstraint
{ ( ! inlineInput || ! 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;
}
onChange={ rangeInputOnChange }
step={ minRangeStep }
min={ minConstraint }
max={ maxConstraint }
ref={ minRange }
disabled={ isLoading }
tabIndex={ showInputFields ? -1 : 0 }
/>
<input
type="range"
className="wc-block-price-filter__range-input wc-block-price-filter__range-input--max wc-block-components-price-slider__range-input wc-block-components-price-slider__range-input--max"
aria-label={ __(
'Filter products by maximum price',
'woo-gutenberg-products-block'
) }
aria-valuetext={ ariaReadableMaxPrice }
value={
Number.isFinite( maxPrice )
? maxPrice
: maxConstraint
setMinPriceInput( value );
} }
onBlur={ priceInputOnBlur }
disabled={ isLoading || ! hasValidConstraints }
value={ minPriceInput }
/>
{ inlineInput && 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;
}
onChange={ rangeInputOnChange }
step={ maxRangeStep }
min={ minConstraint }
max={ maxConstraint }
ref={ maxRange }
disabled={ isLoading }
tabIndex={ showInputFields ? -1 : 0 }
/>
</div>
) }
</div>
<div className="wc-block-price-filter__controls wc-block-components-price-slider__controls">
{ showInputFields && (
<>
setMaxPriceInput( value );
} }
onBlur={ priceInputOnBlur }
disabled={ isLoading || ! hasValidConstraints }
value={ maxPriceInput }
/>
</div>
) }

{ ! showInputFields &&
! isLoading &&
Number.isFinite( minPrice ) &&
Number.isFinite( maxPrice ) && (
<div className="wc-block-price-filter__range-text wc-block-components-price-slider__range-text">
<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 }
value={ minPrice }
/>
<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 }
value={ maxPrice }
/>
</>
</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'
) }
/>
) }
{ ! showInputFields &&
! isLoading &&
Number.isFinite( minPrice ) &&
Number.isFinite( maxPrice ) && (
<div className="wc-block-price-filter__range-text wc-block-components-price-slider__range-text">
{ __( 'Price', 'woo-gutenberg-products-block' ) }
: &nbsp;
<FormattedMonetaryAmount
currency={ currency }
value={ minPrice }
/>
&nbsp;&ndash;&nbsp;
<FormattedMonetaryAmount
currency={ currency }
value={ maxPrice }
/>
</div>
) }
{ showFilterButton && (
<FilterSubmitButton
className="wc-block-price-filter__button wc-block-components-price-slider__button"
Expand Down
Loading