Unify Chip styles (https://github.com/woocommerce/woocommerce-blocks/pull/2765)
* Improve cross character used in dropdown selector * Add is-open and has-checked classes to dropdown selector so we stop relying on complex pseudoselector combinations * Update Chip component with new props * Update Chip styles * Update dropdown selector selected chip with the Chip component * Update active filters chip with the Chip component * Style fixes * Update snapshots and add tests * Change onRemove prop signature * Fix wrong bottom margin * Fix misaligned remove icon * Update assets/js/base/components/chip/index.js Co-authored-by: Darren Ethier <darren@roughsmootheng.in> * Update assets/js/base/components/chip/index.js Co-authored-by: Darren Ethier <darren@roughsmootheng.in> * Add missing default prop * Prettier * Ensure showScreenReaderText is a bool * Rename removeOnClick with removeOnAnyClick * Update snapshots * Fix Chip aria-label logic * Split Chip and RemovableChip * Replace chip close character with an icon * Fix outdated comment Co-authored-by: Darren Ethier <darren@roughsmootheng.in>
This commit is contained in:
parent
92067c0d04
commit
8c06276b00
|
@ -4,7 +4,7 @@
|
||||||
import { __, sprintf } from '@wordpress/i18n';
|
import { __, sprintf } from '@wordpress/i18n';
|
||||||
import { DISPLAY_CART_PRICES_INCLUDING_TAX } from '@woocommerce/block-settings';
|
import { DISPLAY_CART_PRICES_INCLUDING_TAX } from '@woocommerce/block-settings';
|
||||||
import LoadingMask from '@woocommerce/base-components/loading-mask';
|
import LoadingMask from '@woocommerce/base-components/loading-mask';
|
||||||
import Chip from '@woocommerce/base-components/chip';
|
import { RemovableChip } from '@woocommerce/base-components/chip';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -51,7 +51,7 @@ const TotalsDiscountItem = ( {
|
||||||
>
|
>
|
||||||
<ul className="wc-block-components-totals-discount__coupon-list">
|
<ul className="wc-block-components-totals-discount__coupon-list">
|
||||||
{ cartCoupons.map( ( cartCoupon ) => (
|
{ cartCoupons.map( ( cartCoupon ) => (
|
||||||
<Chip
|
<RemovableChip
|
||||||
key={ 'coupon-' + cartCoupon.code }
|
key={ 'coupon-' + cartCoupon.code }
|
||||||
className="wc-block-components-totals-discount__coupon-list-item"
|
className="wc-block-components-totals-discount__coupon-list-item"
|
||||||
text={ cartCoupon.code }
|
text={ cartCoupon.code }
|
||||||
|
@ -68,6 +68,14 @@ const TotalsDiscountItem = ( {
|
||||||
removeCoupon( cartCoupon.code );
|
removeCoupon( cartCoupon.code );
|
||||||
} }
|
} }
|
||||||
radius="large"
|
radius="large"
|
||||||
|
ariaLabel={ sprintf(
|
||||||
|
/* Translators: %s is a coupon code. */
|
||||||
|
__(
|
||||||
|
'Remove coupon "%s"',
|
||||||
|
'woo-gutenberg-products-block'
|
||||||
|
),
|
||||||
|
cartCoupon.code
|
||||||
|
) }
|
||||||
/>
|
/>
|
||||||
) ) }
|
) ) }
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
/**
|
||||||
|
* External dependencies
|
||||||
|
*/
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
import './style.scss';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component used to render a "chip" -- a list item containing some text.
|
||||||
|
*
|
||||||
|
* Each chip defaults to a list element but this can be customized by providing
|
||||||
|
* a wrapperElement.
|
||||||
|
*/
|
||||||
|
const Chip = ( {
|
||||||
|
text,
|
||||||
|
screenReaderText = '',
|
||||||
|
element = 'li',
|
||||||
|
className = '',
|
||||||
|
radius = 'small',
|
||||||
|
children = null,
|
||||||
|
...props
|
||||||
|
} ) => {
|
||||||
|
const Wrapper = element;
|
||||||
|
const wrapperClassName = classNames(
|
||||||
|
className,
|
||||||
|
'wc-block-components-chip',
|
||||||
|
'wc-block-components-chip--radius-' + radius
|
||||||
|
);
|
||||||
|
|
||||||
|
const showScreenReaderText = Boolean(
|
||||||
|
screenReaderText && screenReaderText !== text
|
||||||
|
);
|
||||||
|
|
||||||
|
return (
|
||||||
|
// @ts-ignore
|
||||||
|
<Wrapper className={ wrapperClassName } { ...props }>
|
||||||
|
<span
|
||||||
|
aria-hidden={ showScreenReaderText }
|
||||||
|
className="wc-block-components-chip__text"
|
||||||
|
>
|
||||||
|
{ text }
|
||||||
|
</span>
|
||||||
|
{ showScreenReaderText && (
|
||||||
|
<span className="screen-reader-text">{ screenReaderText }</span>
|
||||||
|
) }
|
||||||
|
{ children }
|
||||||
|
</Wrapper>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Chip.propTypes = {
|
||||||
|
text: PropTypes.node.isRequired,
|
||||||
|
screenReaderText: PropTypes.string,
|
||||||
|
element: PropTypes.elementType,
|
||||||
|
className: PropTypes.string,
|
||||||
|
radius: PropTypes.oneOf( [ 'none', 'small', 'medium', 'large' ] ),
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Chip;
|
|
@ -1,70 +1,2 @@
|
||||||
/**
|
export { default as Chip } from './chip';
|
||||||
* External dependencies
|
export { default as RemovableChip } from './removable-chip';
|
||||||
*/
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import classNames from 'classnames';
|
|
||||||
import { __, sprintf } from '@wordpress/i18n';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal dependencies
|
|
||||||
*/
|
|
||||||
import './style.scss';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Component used to render a "chip" -- a list item containing some text with
|
|
||||||
* an X button to remove/dismiss each chip.
|
|
||||||
*
|
|
||||||
* Each chip defaults to a list element but this can be customized by providing
|
|
||||||
* a wrapperElement.
|
|
||||||
*/
|
|
||||||
const Chip = ( {
|
|
||||||
text,
|
|
||||||
screenReaderText,
|
|
||||||
element = 'li',
|
|
||||||
className = '',
|
|
||||||
onRemove = () => {},
|
|
||||||
disabled = false,
|
|
||||||
radius = 'small',
|
|
||||||
} ) => {
|
|
||||||
const Wrapper = element;
|
|
||||||
const wrapperClassName = classNames(
|
|
||||||
className,
|
|
||||||
'wc-block-components-chip',
|
|
||||||
'wc-block-components-chip--radius-' + radius
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
// @ts-ignore
|
|
||||||
<Wrapper className={ wrapperClassName }>
|
|
||||||
<span aria-hidden="true" className="wc-block-components-chip__text">
|
|
||||||
{ text }
|
|
||||||
</span>
|
|
||||||
<span className="screen-reader-text">
|
|
||||||
{ screenReaderText ? screenReaderText : text }
|
|
||||||
</span>
|
|
||||||
<button
|
|
||||||
className="wc-block-components-chip__remove"
|
|
||||||
onClick={ onRemove }
|
|
||||||
disabled={ disabled }
|
|
||||||
aria-label={ sprintf(
|
|
||||||
/* translators: %s chip text. */
|
|
||||||
__( 'Remove coupon "%s"', 'woo-gutenberg-products-block' ),
|
|
||||||
text
|
|
||||||
) }
|
|
||||||
>
|
|
||||||
✕
|
|
||||||
</button>
|
|
||||||
</Wrapper>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
Chip.propTypes = {
|
|
||||||
text: PropTypes.string.isRequired,
|
|
||||||
screenReaderText: PropTypes.string,
|
|
||||||
element: PropTypes.elementType,
|
|
||||||
className: PropTypes.string,
|
|
||||||
onRemove: PropTypes.func,
|
|
||||||
radius: PropTypes.oneOf( [ 'none', 'small', 'medium', 'large' ] ),
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Chip;
|
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
/**
|
||||||
|
* External dependencies
|
||||||
|
*/
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
import { __, sprintf } from '@wordpress/i18n';
|
||||||
|
import { Icon, noAlt } from '@woocommerce/icons';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal dependencies
|
||||||
|
*/
|
||||||
|
import { Chip } from './index.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component used to render a "chip" -- an item containing some text with
|
||||||
|
* an X button to remove/dismiss each chip.
|
||||||
|
*/
|
||||||
|
const RemovableChip = ( {
|
||||||
|
ariaLabel = '',
|
||||||
|
className = '',
|
||||||
|
disabled = false,
|
||||||
|
onRemove = () => void null,
|
||||||
|
removeOnAnyClick = false,
|
||||||
|
text,
|
||||||
|
screenReaderText = '',
|
||||||
|
...props
|
||||||
|
} ) => {
|
||||||
|
const RemoveElement = removeOnAnyClick ? 'span' : 'button';
|
||||||
|
|
||||||
|
if ( ! ariaLabel ) {
|
||||||
|
const ariaLabelText =
|
||||||
|
screenReaderText && typeof screenReaderText === 'string'
|
||||||
|
? screenReaderText
|
||||||
|
: text;
|
||||||
|
ariaLabel =
|
||||||
|
typeof ariaLabelText !== 'string'
|
||||||
|
? /* translators: Remove chip. */
|
||||||
|
__( 'Remove', 'woo-gutenberg-products-block' )
|
||||||
|
: sprintf(
|
||||||
|
/* translators: %s text of the chip to remove. */
|
||||||
|
__( 'Remove "%s"', 'woo-gutenberg-products-block' ),
|
||||||
|
ariaLabelText
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const clickableElementProps = {
|
||||||
|
'aria-label': ariaLabel,
|
||||||
|
disabled,
|
||||||
|
onClick: onRemove,
|
||||||
|
onKeyDown: ( e ) => {
|
||||||
|
if ( e.key === 'Backspace' || e.key === 'Delete' ) {
|
||||||
|
onRemove();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const chipProps = removeOnAnyClick ? clickableElementProps : {};
|
||||||
|
const removeProps = removeOnAnyClick
|
||||||
|
? { 'aria-hidden': true }
|
||||||
|
: clickableElementProps;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Chip
|
||||||
|
{ ...props }
|
||||||
|
{ ...chipProps }
|
||||||
|
className={ classNames( className, 'is-removable' ) }
|
||||||
|
element={ removeOnAnyClick ? 'button' : props.element }
|
||||||
|
screenReaderText={ screenReaderText }
|
||||||
|
text={ text }
|
||||||
|
>
|
||||||
|
<RemoveElement
|
||||||
|
className="wc-block-components-chip__remove"
|
||||||
|
{ ...removeProps }
|
||||||
|
>
|
||||||
|
<Icon srcElement={ noAlt } size={ 16 } />
|
||||||
|
</RemoveElement>
|
||||||
|
</Chip>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
RemovableChip.propTypes = {
|
||||||
|
text: PropTypes.node.isRequired,
|
||||||
|
ariaLabel: PropTypes.string,
|
||||||
|
className: PropTypes.string,
|
||||||
|
disabled: PropTypes.bool,
|
||||||
|
onRemove: PropTypes.func,
|
||||||
|
removeOnAnyClick: PropTypes.bool,
|
||||||
|
screenReaderText: PropTypes.string,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RemovableChip;
|
|
@ -1,13 +1,23 @@
|
||||||
.wc-block-components-chip {
|
.wc-block-components-chip {
|
||||||
display: inline-block;
|
@include reset-typography();
|
||||||
background: $core-grey-light-500;
|
align-items: center;
|
||||||
padding: 0.365em 0.5em;
|
border: 0;
|
||||||
|
display: inline-flex;
|
||||||
|
padding: em($gap-smallest / 2) 0.5em em($gap-smallest);
|
||||||
margin: 0 0.365em 0.365em 0;
|
margin: 0 0.365em 0.365em 0;
|
||||||
color: $core-grey-dark-800;
|
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
line-height: 1em;
|
line-height: 1;
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
|
||||||
|
// Chip might be a button, so we need to override theme styles.
|
||||||
|
&,
|
||||||
|
&:hover,
|
||||||
|
&:focus,
|
||||||
|
&:active {
|
||||||
|
background: $core-grey-light-500;
|
||||||
|
color: $core-grey-dark-800;
|
||||||
|
}
|
||||||
|
|
||||||
&.wc-block-components-chip--radius-small {
|
&.wc-block-components-chip--radius-small {
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
}
|
}
|
||||||
|
@ -15,30 +25,41 @@
|
||||||
border-radius: 0.433em;
|
border-radius: 0.433em;
|
||||||
}
|
}
|
||||||
&.wc-block-components-chip--radius-large {
|
&.wc-block-components-chip--radius-large {
|
||||||
border-radius: 0.865em;
|
border-radius: 2em;
|
||||||
padding: 0.365em 0.75em;
|
padding-left: 0.75em;
|
||||||
|
padding-right: 0.75em;
|
||||||
}
|
}
|
||||||
.wc-block-components-chip__text {
|
.wc-block-components-chip__text {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
&.is-removable {
|
||||||
padding-right: 0.5em;
|
padding-right: 0.5em;
|
||||||
}
|
}
|
||||||
|
&.is-removable .wc-block-components-chip__text {
|
||||||
|
padding-right: 0.25em;
|
||||||
|
}
|
||||||
.wc-block-components-chip__remove {
|
.wc-block-components-chip__remove {
|
||||||
@include font-size(smaller);
|
@include font-size(smaller);
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border: 0;
|
border: 0;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
float: none;
|
padding: 0;
|
||||||
vertical-align: middle;
|
|
||||||
line-height: 1.33em;
|
|
||||||
padding: 0.66em; // Should equate to ~8px; chip has ~6px padding, and font size difference/2 is 2px.
|
|
||||||
margin: -0.66em;
|
|
||||||
|
|
||||||
&:hover,
|
> .dashicon {
|
||||||
&:focus {
|
vertical-align: middle;
|
||||||
color: #d94f4f;
|
|
||||||
}
|
|
||||||
&:disabled {
|
|
||||||
color: $core-grey-dark-100;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
button.wc-block-components-chip:hover > .wc-block-components-chip__remove,
|
||||||
|
button.wc-block-components-chip:focus > .wc-block-components-chip__remove,
|
||||||
|
.wc-block-components-chip__remove:hover,
|
||||||
|
.wc-block-components-chip__remove:focus {
|
||||||
|
fill: #d94f4f;
|
||||||
|
}
|
||||||
|
|
||||||
|
button.wc-block-components-chip:disabled > .wc-block-components-chip__remove,
|
||||||
|
.wc-block-components-chip__remove:disabled {
|
||||||
|
fill: $core-grey-dark-100;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
|
@ -1,105 +1,312 @@
|
||||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||||
|
|
||||||
|
exports[`Chip should render children nodes 1`] = `
|
||||||
|
<li
|
||||||
|
className="wc-block-components-chip wc-block-components-chip--radius-small"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-hidden={false}
|
||||||
|
className="wc-block-components-chip__text"
|
||||||
|
>
|
||||||
|
Test
|
||||||
|
</span>
|
||||||
|
Lorem Ipsum
|
||||||
|
</li>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Chip should render defined radius 1`] = `
|
||||||
|
<li
|
||||||
|
className="wc-block-components-chip wc-block-components-chip--radius-large"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-hidden={false}
|
||||||
|
className="wc-block-components-chip__text"
|
||||||
|
>
|
||||||
|
Test
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Chip should render nodes as the text 1`] = `
|
||||||
|
<li
|
||||||
|
className="wc-block-components-chip wc-block-components-chip--radius-small"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-hidden={false}
|
||||||
|
className="wc-block-components-chip__text"
|
||||||
|
>
|
||||||
|
<h1>
|
||||||
|
Test
|
||||||
|
</h1>
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Chip should render screen reader text 1`] = `
|
||||||
|
<li
|
||||||
|
className="wc-block-components-chip wc-block-components-chip--radius-small"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-hidden={true}
|
||||||
|
className="wc-block-components-chip__text"
|
||||||
|
>
|
||||||
|
Test
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
className="screen-reader-text"
|
||||||
|
>
|
||||||
|
Test 2
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Chip should render text 1`] = `
|
||||||
|
<li
|
||||||
|
className="wc-block-components-chip wc-block-components-chip--radius-small"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-hidden={false}
|
||||||
|
className="wc-block-components-chip__text"
|
||||||
|
>
|
||||||
|
Test
|
||||||
|
</span>
|
||||||
|
</li>
|
||||||
|
`;
|
||||||
|
|
||||||
exports[`Chip with custom wrapper should render a chip made up of a div instead of a li 1`] = `
|
exports[`Chip with custom wrapper should render a chip made up of a div instead of a li 1`] = `
|
||||||
<div
|
<div
|
||||||
className="wc-block-components-chip wc-block-components-chip--radius-small"
|
className="wc-block-components-chip wc-block-components-chip--radius-small"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
aria-hidden="true"
|
aria-hidden={false}
|
||||||
className="wc-block-components-chip__text"
|
className="wc-block-components-chip__text"
|
||||||
>
|
>
|
||||||
Test
|
Test
|
||||||
</span>
|
</span>
|
||||||
<span
|
|
||||||
className="screen-reader-text"
|
|
||||||
>
|
|
||||||
Test
|
|
||||||
</span>
|
|
||||||
<button
|
|
||||||
aria-label="Remove coupon \\"Test\\""
|
|
||||||
className="wc-block-components-chip__remove"
|
|
||||||
disabled={false}
|
|
||||||
onClick={[Function]}
|
|
||||||
>
|
|
||||||
✕
|
|
||||||
</button>
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Chip without custom wrapper should render defined radius 1`] = `
|
exports[`RemovableChip should render custom aria label 1`] = `
|
||||||
<li
|
<li
|
||||||
className="wc-block-components-chip wc-block-components-chip--radius-large"
|
className="is-removable wc-block-components-chip wc-block-components-chip--radius-small"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
aria-hidden="true"
|
aria-hidden={false}
|
||||||
className="wc-block-components-chip__text"
|
className="wc-block-components-chip__text"
|
||||||
>
|
>
|
||||||
|
<h1>
|
||||||
Test
|
Test
|
||||||
</span>
|
</h1>
|
||||||
<span
|
|
||||||
className="screen-reader-text"
|
|
||||||
>
|
|
||||||
Test
|
|
||||||
</span>
|
</span>
|
||||||
<button
|
<button
|
||||||
aria-label="Remove coupon \\"Test\\""
|
aria-label="Aria test"
|
||||||
className="wc-block-components-chip__remove"
|
className="wc-block-components-chip__remove"
|
||||||
disabled={false}
|
disabled={false}
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
|
onKeyDown={[Function]}
|
||||||
>
|
>
|
||||||
✕
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
className="dashicon dashicons-arrow-down-alt2"
|
||||||
|
focusable="false"
|
||||||
|
height={16}
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
width={16}
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M14.95 6.46L11.41 10l3.54 3.54-1.41 1.41L10 11.42l-3.53 3.53-1.42-1.42L8.58 10 5.05 6.47l1.42-1.42L10 8.58l3.54-3.53z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Chip without custom wrapper should render text and the remove button 1`] = `
|
exports[`RemovableChip should render default aria label if text is a node 1`] = `
|
||||||
<li
|
<li
|
||||||
className="wc-block-components-chip wc-block-components-chip--radius-small"
|
className="is-removable wc-block-components-chip wc-block-components-chip--radius-small"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
aria-hidden="true"
|
aria-hidden={true}
|
||||||
className="wc-block-components-chip__text"
|
className="wc-block-components-chip__text"
|
||||||
>
|
>
|
||||||
|
<h1>
|
||||||
Test
|
Test
|
||||||
|
</h1>
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className="screen-reader-text"
|
className="screen-reader-text"
|
||||||
>
|
>
|
||||||
Test
|
Test 2
|
||||||
</span>
|
</span>
|
||||||
<button
|
<button
|
||||||
aria-label="Remove coupon \\"Test\\""
|
aria-label="Remove \\"Test 2\\""
|
||||||
className="wc-block-components-chip__remove"
|
className="wc-block-components-chip__remove"
|
||||||
disabled={false}
|
disabled={false}
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
|
onKeyDown={[Function]}
|
||||||
>
|
>
|
||||||
✕
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
className="dashicon dashicons-arrow-down-alt2"
|
||||||
|
focusable="false"
|
||||||
|
height={16}
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
width={16}
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M14.95 6.46L11.41 10l3.54 3.54-1.41 1.41L10 11.42l-3.53 3.53-1.42-1.42L8.58 10 5.05 6.47l1.42-1.42L10 8.58l3.54-3.53z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
exports[`Chip without custom wrapper should render with disabled remove button 1`] = `
|
exports[`RemovableChip should render screen reader text aria label 1`] = `
|
||||||
<li
|
<li
|
||||||
className="wc-block-components-chip wc-block-components-chip--radius-small"
|
className="is-removable wc-block-components-chip wc-block-components-chip--radius-small"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
aria-hidden="true"
|
aria-hidden={true}
|
||||||
className="wc-block-components-chip__text"
|
className="wc-block-components-chip__text"
|
||||||
>
|
>
|
||||||
Test
|
Test
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span
|
||||||
className="screen-reader-text"
|
className="screen-reader-text"
|
||||||
|
>
|
||||||
|
Test 2
|
||||||
|
</span>
|
||||||
|
<button
|
||||||
|
aria-label="Remove \\"Test 2\\""
|
||||||
|
className="wc-block-components-chip__remove"
|
||||||
|
disabled={false}
|
||||||
|
onClick={[Function]}
|
||||||
|
onKeyDown={[Function]}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
className="dashicon dashicons-arrow-down-alt2"
|
||||||
|
focusable="false"
|
||||||
|
height={16}
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
width={16}
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M14.95 6.46L11.41 10l3.54 3.54-1.41 1.41L10 11.42l-3.53 3.53-1.42-1.42L8.58 10 5.05 6.47l1.42-1.42L10 8.58l3.54-3.53z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`RemovableChip should render text and the remove button 1`] = `
|
||||||
|
<li
|
||||||
|
className="is-removable wc-block-components-chip wc-block-components-chip--radius-small"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-hidden={false}
|
||||||
|
className="wc-block-components-chip__text"
|
||||||
>
|
>
|
||||||
Test
|
Test
|
||||||
</span>
|
</span>
|
||||||
<button
|
<button
|
||||||
aria-label="Remove coupon \\"Test\\""
|
aria-label="Remove \\"Test\\""
|
||||||
|
className="wc-block-components-chip__remove"
|
||||||
|
disabled={false}
|
||||||
|
onClick={[Function]}
|
||||||
|
onKeyDown={[Function]}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
className="dashicon dashicons-arrow-down-alt2"
|
||||||
|
focusable="false"
|
||||||
|
height={16}
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
width={16}
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M14.95 6.46L11.41 10l3.54 3.54-1.41 1.41L10 11.42l-3.53 3.53-1.42-1.42L8.58 10 5.05 6.47l1.42-1.42L10 8.58l3.54-3.53z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`RemovableChip should render with disabled remove button 1`] = `
|
||||||
|
<li
|
||||||
|
className="is-removable wc-block-components-chip wc-block-components-chip--radius-small"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-hidden={false}
|
||||||
|
className="wc-block-components-chip__text"
|
||||||
|
>
|
||||||
|
Test
|
||||||
|
</span>
|
||||||
|
<button
|
||||||
|
aria-label="Remove \\"Test\\""
|
||||||
className="wc-block-components-chip__remove"
|
className="wc-block-components-chip__remove"
|
||||||
disabled={true}
|
disabled={true}
|
||||||
onClick={[Function]}
|
onClick={[Function]}
|
||||||
|
onKeyDown={[Function]}
|
||||||
>
|
>
|
||||||
✕
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
className="dashicon dashicons-arrow-down-alt2"
|
||||||
|
focusable="false"
|
||||||
|
height={16}
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
width={16}
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M14.95 6.46L11.41 10l3.54 3.54-1.41 1.41L10 11.42l-3.53 3.53-1.42-1.42L8.58 10 5.05 6.47l1.42-1.42L10 8.58l3.54-3.53z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
</li>
|
</li>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
exports[`RemovableChip with removeOnAnyClick should be a button when removeOnAnyClick is set to true 1`] = `
|
||||||
|
<button
|
||||||
|
aria-label="Remove \\"Test\\""
|
||||||
|
className="is-removable wc-block-components-chip wc-block-components-chip--radius-small"
|
||||||
|
disabled={false}
|
||||||
|
onClick={[Function]}
|
||||||
|
onKeyDown={[Function]}
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-hidden={false}
|
||||||
|
className="wc-block-components-chip__text"
|
||||||
|
>
|
||||||
|
Test
|
||||||
|
</span>
|
||||||
|
<span
|
||||||
|
aria-hidden={true}
|
||||||
|
className="wc-block-components-chip__remove"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
aria-hidden="true"
|
||||||
|
className="dashicon dashicons-arrow-down-alt2"
|
||||||
|
focusable="false"
|
||||||
|
height={16}
|
||||||
|
role="img"
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
width={16}
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M14.95 6.46L11.41 10l3.54 3.54-1.41 1.41L10 11.42l-3.53 3.53-1.42-1.42L8.58 10 5.05 6.47l1.42-1.42L10 8.58l3.54-3.53z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
`;
|
||||||
|
|
|
@ -6,16 +6,23 @@ import TestRenderer from 'react-test-renderer';
|
||||||
/**
|
/**
|
||||||
* Internal dependencies
|
* Internal dependencies
|
||||||
*/
|
*/
|
||||||
import Chip from '../';
|
import { Chip, RemovableChip } from '..';
|
||||||
|
|
||||||
describe( 'Chip', () => {
|
describe( 'Chip', () => {
|
||||||
describe( 'without custom wrapper', () => {
|
test( 'should render text', () => {
|
||||||
test( 'should render text and the remove button', () => {
|
|
||||||
const component = TestRenderer.create( <Chip text="Test" /> );
|
const component = TestRenderer.create( <Chip text="Test" /> );
|
||||||
|
|
||||||
expect( component.toJSON() ).toMatchSnapshot();
|
expect( component.toJSON() ).toMatchSnapshot();
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
test( 'should render nodes as the text', () => {
|
||||||
|
const component = TestRenderer.create(
|
||||||
|
<Chip text={ <h1>Test</h1> } />
|
||||||
|
);
|
||||||
|
|
||||||
|
expect( component.toJSON() ).toMatchSnapshot();
|
||||||
|
} );
|
||||||
|
|
||||||
test( 'should render defined radius', () => {
|
test( 'should render defined radius', () => {
|
||||||
const component = TestRenderer.create(
|
const component = TestRenderer.create(
|
||||||
<Chip text="Test" radius="large" />
|
<Chip text="Test" radius="large" />
|
||||||
|
@ -24,13 +31,20 @@ describe( 'Chip', () => {
|
||||||
expect( component.toJSON() ).toMatchSnapshot();
|
expect( component.toJSON() ).toMatchSnapshot();
|
||||||
} );
|
} );
|
||||||
|
|
||||||
test( 'should render with disabled remove button', () => {
|
test( 'should render screen reader text', () => {
|
||||||
const component = TestRenderer.create(
|
const component = TestRenderer.create(
|
||||||
<Chip text="Test" disabled={ true } />
|
<Chip text="Test" screenReaderText="Test 2" />
|
||||||
);
|
);
|
||||||
|
|
||||||
expect( component.toJSON() ).toMatchSnapshot();
|
expect( component.toJSON() ).toMatchSnapshot();
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
test( 'should render children nodes', () => {
|
||||||
|
const component = TestRenderer.create(
|
||||||
|
<Chip text="Test">Lorem Ipsum</Chip>
|
||||||
|
);
|
||||||
|
|
||||||
|
expect( component.toJSON() ).toMatchSnapshot();
|
||||||
} );
|
} );
|
||||||
|
|
||||||
describe( 'with custom wrapper', () => {
|
describe( 'with custom wrapper', () => {
|
||||||
|
@ -43,3 +57,53 @@ describe( 'Chip', () => {
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
} );
|
} );
|
||||||
|
|
||||||
|
describe( 'RemovableChip', () => {
|
||||||
|
test( 'should render text and the remove button', () => {
|
||||||
|
const component = TestRenderer.create( <RemovableChip text="Test" /> );
|
||||||
|
|
||||||
|
expect( component.toJSON() ).toMatchSnapshot();
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should render with disabled remove button', () => {
|
||||||
|
const component = TestRenderer.create(
|
||||||
|
<RemovableChip text="Test" disabled={ true } />
|
||||||
|
);
|
||||||
|
|
||||||
|
expect( component.toJSON() ).toMatchSnapshot();
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should render custom aria label', () => {
|
||||||
|
const component = TestRenderer.create(
|
||||||
|
<RemovableChip text={ <h1>Test</h1> } ariaLabel="Aria test" />
|
||||||
|
);
|
||||||
|
|
||||||
|
expect( component.toJSON() ).toMatchSnapshot();
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should render default aria label if text is a node', () => {
|
||||||
|
const component = TestRenderer.create(
|
||||||
|
<RemovableChip text={ <h1>Test</h1> } screenReaderText="Test 2" />
|
||||||
|
);
|
||||||
|
|
||||||
|
expect( component.toJSON() ).toMatchSnapshot();
|
||||||
|
} );
|
||||||
|
|
||||||
|
test( 'should render screen reader text aria label', () => {
|
||||||
|
const component = TestRenderer.create(
|
||||||
|
<RemovableChip text="Test" screenReaderText="Test 2" />
|
||||||
|
);
|
||||||
|
|
||||||
|
expect( component.toJSON() ).toMatchSnapshot();
|
||||||
|
} );
|
||||||
|
|
||||||
|
describe( 'with removeOnAnyClick', () => {
|
||||||
|
test( 'should be a button when removeOnAnyClick is set to true', () => {
|
||||||
|
const component = TestRenderer.create(
|
||||||
|
<RemovableChip text="Test" removeOnAnyClick={ true } />
|
||||||
|
);
|
||||||
|
|
||||||
|
expect( component.toJSON() ).toMatchSnapshot();
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
} );
|
||||||
|
|
|
@ -91,6 +91,8 @@ const DropdownSelector = ( {
|
||||||
className={ classNames( classes, {
|
className={ classNames( classes, {
|
||||||
'is-multiple': multiple,
|
'is-multiple': multiple,
|
||||||
'is-single': ! multiple,
|
'is-single': ! multiple,
|
||||||
|
'has-checked': checked.length > 0,
|
||||||
|
'is-open': isOpen,
|
||||||
} ) }
|
} ) }
|
||||||
>
|
>
|
||||||
{ /* eslint-disable-next-line jsx-a11y/label-has-for */ }
|
{ /* eslint-disable-next-line jsx-a11y/label-has-for */ }
|
||||||
|
|
|
@ -2,31 +2,23 @@
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
import { __, sprintf } from '@wordpress/i18n';
|
import { __, sprintf } from '@wordpress/i18n';
|
||||||
|
import { RemovableChip } from '@woocommerce/base-components/chip';
|
||||||
|
|
||||||
const DropdownSelectorSelectedChip = ( { onRemoveItem, option } ) => {
|
const DropdownSelectorSelectedChip = ( { onRemoveItem, option } ) => {
|
||||||
return (
|
return (
|
||||||
<button
|
<RemovableChip
|
||||||
className="wc-block-dropdown-selector__selected-chip wc-block-components-dropdown-selector__selected-chip"
|
className="wc-block-dropdown-selector__selected-chip wc-block-components-dropdown-selector__selected-chip"
|
||||||
onClick={ () => {
|
removeOnAnyClick={ true }
|
||||||
|
onRemove={ () => {
|
||||||
onRemoveItem( option.value );
|
onRemoveItem( option.value );
|
||||||
} }
|
} }
|
||||||
onKeyDown={ ( e ) => {
|
ariaLabel={ sprintf(
|
||||||
if ( e.key === 'Backspace' || e.key === 'Delete' ) {
|
|
||||||
onRemoveItem( option.value );
|
|
||||||
}
|
|
||||||
} }
|
|
||||||
aria-label={ sprintf(
|
|
||||||
__( 'Remove %s filter', 'woo-gutenberg-products-block' ),
|
__( 'Remove %s filter', 'woo-gutenberg-products-block' ),
|
||||||
option.name
|
option.name
|
||||||
) }
|
) }
|
||||||
>
|
text={ option.label }
|
||||||
<span className="wc-block-dropdown-selector__selected-chip__label wc-block-components-dropdown-selector__selected-chip__label">
|
radius="large"
|
||||||
{ option.label }
|
/>
|
||||||
</span>
|
|
||||||
<span className="wc-block-dropdown-selector__selected-chip__remove wc-block-components-dropdown-selector__selected-chip__remove">
|
|
||||||
𝘅
|
|
||||||
</span>
|
|
||||||
</button>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*/
|
*/
|
||||||
import { __, sprintf } from '@wordpress/i18n';
|
import { __, sprintf } from '@wordpress/i18n';
|
||||||
import { useEffect, useRef } from '@wordpress/element';
|
import { useEffect, useRef } from '@wordpress/element';
|
||||||
|
import { Icon, noAlt } from '@woocommerce/icons';
|
||||||
|
|
||||||
const DropdownSelectorSelectedValue = ( { onClick, onRemoveItem, option } ) => {
|
const DropdownSelectorSelectedValue = ( { onClick, onRemoveItem, option } ) => {
|
||||||
const labelRef = useRef( null );
|
const labelRef = useRef( null );
|
||||||
|
@ -47,7 +48,7 @@ const DropdownSelectorSelectedValue = ( { onClick, onRemoveItem, option } ) => {
|
||||||
option.name
|
option.name
|
||||||
) }
|
) }
|
||||||
>
|
>
|
||||||
𝘅
|
<Icon srcElement={ noAlt } size={ 16 } />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
// 18px is the minimum input field line-height and 14px is the font-size of
|
||||||
|
// the drop down selector elements.
|
||||||
|
$dropdown-selector-line-height: 18/14;
|
||||||
|
|
||||||
.wc-block-components-dropdown-selector {
|
.wc-block-components-dropdown-selector {
|
||||||
max-width: 300px;
|
max-width: 300px;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -5,34 +9,37 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.wc-block-components-dropdown-selector__input-wrapper {
|
.wc-block-components-dropdown-selector__input-wrapper {
|
||||||
|
background: #fff;
|
||||||
|
border: 1px solid $input-border-gray;
|
||||||
|
color: $input-text-active;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border: 1px solid #9f9f9f;
|
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
cursor: text;
|
cursor: text;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
padding: 2px;
|
padding: 2px $gap-smaller;
|
||||||
|
|
||||||
.is-disabled & {
|
.is-disabled & {
|
||||||
background-color: $core-grey-light-500;
|
background-color: $core-grey-light-500;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.wc-block-components-dropdown-selector__placeholder {
|
.is-multiple.has-checked > & {
|
||||||
@include font-size(small);
|
padding: 2px $gap-smallest;
|
||||||
height: 1.8em;
|
}
|
||||||
margin: 0 $gap-smallest;
|
|
||||||
white-space: nowrap;
|
.is-open > & {
|
||||||
|
border-radius: 4px 4px 0 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.wc-block-components-dropdown-selector__input {
|
.wc-block-components-dropdown-selector__input {
|
||||||
@include font-size(small);
|
@include font-size(small);
|
||||||
height: 1.8em;
|
line-height: $dropdown-selector-line-height;
|
||||||
|
margin: em($gap-small/4) 0;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
padding: em($gap-smallest * 0.75) 0 em($gap-smallest * 0.75);
|
||||||
|
|
||||||
.is-single & {
|
.is-single & {
|
||||||
margin: 0 4px;
|
|
||||||
padding: 0;
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
||||||
&:hover,
|
&:hover,
|
||||||
|
@ -40,24 +47,23 @@
|
||||||
&:active {
|
&:active {
|
||||||
outline: 0;
|
outline: 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&:not(:first-child):focus {
|
.is-single.has-checked.is-open & {
|
||||||
margin-bottom: 1.5px;
|
margin-bottom: 1.5px;
|
||||||
margin-top: 1.5px;
|
margin-top: 1.5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:not(:first-child):not(:focus) {
|
.is-single.has-checked:not(.is-open) & {
|
||||||
@include visually-hidden();
|
@include visually-hidden();
|
||||||
// Fixes an issue in Firefox that `flex: wrap` in the container was making
|
// Fixes an issue in Firefox that `flex: wrap` in the container was making
|
||||||
// this element to still occupy one line.
|
// this element to still occupy one line.
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
.is-multiple & {
|
.is-multiple & {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
margin: 1.5px;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,7 +82,6 @@
|
||||||
|
|
||||||
.wc-block-components-dropdown-selector {
|
.wc-block-components-dropdown-selector {
|
||||||
// Reset <button> styles
|
// Reset <button> styles
|
||||||
.wc-block-components-dropdown-selector__selected-chip,
|
|
||||||
.wc-block-components-dropdown-selector__selected-value__label,
|
.wc-block-components-dropdown-selector__selected-value__label,
|
||||||
.wc-block-components-dropdown-selector__selected-value__remove {
|
.wc-block-components-dropdown-selector__selected-value__remove {
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
|
@ -95,50 +100,39 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.wc-block-components-dropdown-selector__selected-value {
|
.wc-block-components-dropdown-selector__selected-value {
|
||||||
|
@include font-size(small);
|
||||||
align-items: center;
|
align-items: center;
|
||||||
color: $core-grey-dark-600;
|
color: $core-grey-dark-600;
|
||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
height: 1.8em;
|
margin: em($gap-small/4) 0;
|
||||||
padding: 1.5px 1.5px 1.5px 4px;
|
padding: em($gap-smallest * 0.75) 0 em($gap-smallest * 0.75);
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wc-block-components-dropdown-selector__selected-chip {
|
.wc-block-components-dropdown-selector__selected-value__label {
|
||||||
align-items: center;
|
|
||||||
background-color: $core-grey-light-600;
|
|
||||||
border: 1px solid #9f9f9f;
|
|
||||||
border-radius: 4px;
|
|
||||||
color: $core-grey-dark-600;
|
|
||||||
display: inline-flex;
|
|
||||||
height: 1.8em;
|
|
||||||
margin: 1.5px;
|
|
||||||
padding: 0 0 0 4px;
|
|
||||||
white-space: nowrap;
|
|
||||||
|
|
||||||
&:hover,
|
|
||||||
&:focus,
|
|
||||||
&:active {
|
|
||||||
background-color: $core-grey-light-400;
|
|
||||||
border: 1px solid #9f9f9f;
|
|
||||||
color: $core-grey-dark-600;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.wc-block-components-dropdown-selector__selected-value__label,
|
|
||||||
.wc-block-components-dropdown-selector__selected-chip__label {
|
|
||||||
@include font-size(small);
|
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
|
line-height: $dropdown-selector-line-height;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wc-block-components-dropdown-selector__selected-value__remove,
|
.wc-block-components-dropdown-selector__selected-value__remove {
|
||||||
.wc-block-components-dropdown-selector__selected-chip__remove {
|
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border: 0;
|
border: 0;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
padding: 0 0.3em;
|
padding: 0 0 0 0.3em;
|
||||||
|
|
||||||
|
> .dashicon {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.wc-block-components-dropdown-selector__selected-chip {
|
||||||
|
@include font-size(small);
|
||||||
|
margin-top: em($gap-small/4);
|
||||||
|
margin-bottom: em($gap-small/4);
|
||||||
|
line-height: $dropdown-selector-line-height;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ const ActiveAttributeFilters = ( {
|
||||||
attributeObject = {},
|
attributeObject = {},
|
||||||
slugs = [],
|
slugs = [],
|
||||||
operator = 'in',
|
operator = 'in',
|
||||||
|
displayStyle,
|
||||||
} ) => {
|
} ) => {
|
||||||
const { results, isLoading } = useCollection( {
|
const { results, isLoading } = useCollection( {
|
||||||
namespace: '/wc/store',
|
namespace: '/wc/store',
|
||||||
|
@ -74,6 +75,7 @@ const ActiveAttributeFilters = ( {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
showLabel: false,
|
showLabel: false,
|
||||||
|
displayStyle,
|
||||||
} );
|
} );
|
||||||
} ) }
|
} ) }
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -41,6 +41,7 @@ const ActiveFiltersBlock = ( {
|
||||||
setMinPrice( undefined );
|
setMinPrice( undefined );
|
||||||
setMaxPrice( undefined );
|
setMaxPrice( undefined );
|
||||||
},
|
},
|
||||||
|
displayStyle: blockAttributes.displayStyle,
|
||||||
} );
|
} );
|
||||||
}, [ minPrice, maxPrice, formatPriceRange ] );
|
}, [ minPrice, maxPrice, formatPriceRange ] );
|
||||||
|
|
||||||
|
@ -52,6 +53,7 @@ const ActiveFiltersBlock = ( {
|
||||||
return (
|
return (
|
||||||
<ActiveAttributeFilters
|
<ActiveAttributeFilters
|
||||||
attributeObject={ attributeObject }
|
attributeObject={ attributeObject }
|
||||||
|
displayStyle={ blockAttributes.displayStyle }
|
||||||
slugs={ attribute.slug }
|
slugs={ attribute.slug }
|
||||||
key={ attribute.attribute }
|
key={ attribute.attribute }
|
||||||
operator={ attribute.operator }
|
operator={ attribute.operator }
|
||||||
|
@ -96,6 +98,7 @@ const ActiveFiltersBlock = ( {
|
||||||
'Small',
|
'Small',
|
||||||
'woo-gutenberg-products-block'
|
'woo-gutenberg-products-block'
|
||||||
),
|
),
|
||||||
|
displayStyle: blockAttributes.displayStyle,
|
||||||
} ) }
|
} ) }
|
||||||
{ renderRemovableListItem( {
|
{ renderRemovableListItem( {
|
||||||
type: __(
|
type: __(
|
||||||
|
@ -106,6 +109,7 @@ const ActiveFiltersBlock = ( {
|
||||||
'Blue',
|
'Blue',
|
||||||
'woo-gutenberg-products-block'
|
'woo-gutenberg-products-block'
|
||||||
),
|
),
|
||||||
|
displayStyle: blockAttributes.displayStyle,
|
||||||
} ) }
|
} ) }
|
||||||
</Fragment>
|
</Fragment>
|
||||||
) : (
|
) : (
|
||||||
|
|
|
@ -5,16 +5,20 @@
|
||||||
.wc-block-active-filters__clear-all {
|
.wc-block-active-filters__clear-all {
|
||||||
@include font-size(regular);
|
@include font-size(regular);
|
||||||
float: right;
|
float: right;
|
||||||
background: transparent none;
|
|
||||||
border: none;
|
border: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
&:hover {
|
&,
|
||||||
background: transparent none;
|
&:hover,
|
||||||
|
&:focus,
|
||||||
|
&:active {
|
||||||
|
background: transparent;
|
||||||
|
color: inherit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.wc-block-active-filters__list {
|
.wc-block-active-filters__list {
|
||||||
margin: 0 0 $gap-smallest;
|
margin: 0 0 $gap-smallest;
|
||||||
list-style: none outside;
|
list-style: none outside;
|
||||||
|
@ -32,6 +36,14 @@
|
||||||
list-style: none outside;
|
list-style: none outside;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
.wc-block-active-filters__list-item-type {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.wc-block-active-filters__list-item-type {
|
.wc-block-active-filters__list-item-type {
|
||||||
@include font-size(smaller);
|
@include font-size(smaller);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
|
@ -52,14 +64,7 @@
|
||||||
padding: 0 16px 0 0;
|
padding: 0 16px 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:first-child {
|
.wc-block-active-filters__list-item-remove {
|
||||||
.wc-block-active-filters__list-item-type {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
button {
|
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border: 0;
|
border: 0;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
|
@ -83,44 +88,20 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.wc-block-active-filters__list--chips {
|
.wc-block-active-filters__list--chips {
|
||||||
|
ul,
|
||||||
li {
|
li {
|
||||||
display: inline-block;
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
.wc-block-active-filters__list-item-type {
|
.wc-block-active-filters__list-item-type {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
.wc-block-active-filters__list-item-name {
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
li.wc-block-active-filters__list-item {
|
|
||||||
background: #c4c4c4;
|
|
||||||
border-radius: 4px;
|
|
||||||
padding: 4px 8px;
|
|
||||||
margin: 0 6px 6px 0;
|
|
||||||
color: #24292d;
|
|
||||||
}
|
|
||||||
button {
|
|
||||||
float: none;
|
|
||||||
vertical-align: middle;
|
|
||||||
margin: -2px 0 0 9px;
|
|
||||||
height: 0;
|
|
||||||
padding: 12px 0 0 0;
|
|
||||||
width: 12px;
|
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
|
||||||
|
|
||||||
&::before {
|
.wc-block-components-chip {
|
||||||
width: 12px;
|
@include font-size(small);
|
||||||
height: 12px;
|
margin-top: em($gap-small/4);
|
||||||
background: transparent url("data:image/svg+xml,%3Csvg width='12' viewBox='0 0 9 9' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Crect x='7.03329' width='2' height='9.9466' transform='rotate(45 7.03329 0)' fill='%2324292d'/%3E%3Crect x='8.4476' y='7.07104' width='2' height='9.9466' transform='rotate(135 8.4476 7.07104)' fill='%2324292d'/%3E%3C/svg%3E%0A") center center no-repeat; /* stylelint-disable-line */
|
margin-bottom: em($gap-small/4);
|
||||||
display: block;
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
*/
|
*/
|
||||||
import { __, sprintf } from '@wordpress/i18n';
|
import { __, sprintf } from '@wordpress/i18n';
|
||||||
import { formatPrice } from '@woocommerce/base-utils';
|
import { formatPrice } from '@woocommerce/base-utils';
|
||||||
import { Fragment } from '@wordpress/element';
|
import { RemovableChip } from '@woocommerce/base-components/chip';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Format a min/max price range to display.
|
* Format a min/max price range to display.
|
||||||
|
@ -44,6 +44,7 @@ export const formatPriceRange = ( minPrice, maxPrice ) => {
|
||||||
* @param {string} listItem.name Name string.
|
* @param {string} listItem.name Name string.
|
||||||
* @param {string} listItem.prefix Prefix shown before item name.
|
* @param {string} listItem.prefix Prefix shown before item name.
|
||||||
* @param {Function} listItem.removeCallback Callback to remove item.
|
* @param {Function} listItem.removeCallback Callback to remove item.
|
||||||
|
* @param {string} listItem.displayStyle Whether it's a list or chips.
|
||||||
* @param {boolean} [listItem.showLabel=true] Should the label be shown for
|
* @param {boolean} [listItem.showLabel=true] Should the label be shown for
|
||||||
* this item?
|
* this item?
|
||||||
*/
|
*/
|
||||||
|
@ -53,7 +54,23 @@ export const renderRemovableListItem = ( {
|
||||||
prefix,
|
prefix,
|
||||||
removeCallback = () => {},
|
removeCallback = () => {},
|
||||||
showLabel = true,
|
showLabel = true,
|
||||||
|
displayStyle,
|
||||||
} ) => {
|
} ) => {
|
||||||
|
const prefixedName = prefix ? (
|
||||||
|
<>
|
||||||
|
{ prefix }
|
||||||
|
|
||||||
|
{ name }
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
name
|
||||||
|
);
|
||||||
|
const removeText = sprintf(
|
||||||
|
/* translators: %s attribute value used in the filter. For example: yellow, green, small, large. */
|
||||||
|
__( 'Remove %s filter', 'woo-gutenberg-products-block' ),
|
||||||
|
name
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<li
|
<li
|
||||||
className="wc-block-active-filters__list-item"
|
className="wc-block-active-filters__list-item"
|
||||||
|
@ -64,27 +81,25 @@ export const renderRemovableListItem = ( {
|
||||||
{ type + ': ' }
|
{ type + ': ' }
|
||||||
</span>
|
</span>
|
||||||
) }
|
) }
|
||||||
<span className="wc-block-active-filters__list-item-name">
|
{ displayStyle === 'chips' ? (
|
||||||
{ prefix ? (
|
<RemovableChip
|
||||||
<Fragment>
|
element="span"
|
||||||
{ prefix }
|
text={ prefixedName }
|
||||||
|
onRemove={ removeCallback }
|
||||||
{ name }
|
radius="large"
|
||||||
</Fragment>
|
ariaLabel={ removeText }
|
||||||
|
/>
|
||||||
) : (
|
) : (
|
||||||
name
|
<span className="wc-block-active-filters__list-item-name">
|
||||||
) }
|
{ prefixedName }
|
||||||
<button onClick={ removeCallback }>
|
<button
|
||||||
{ sprintf(
|
className="wc-block-active-filters__list-item-remove"
|
||||||
/* translators: %s attribute value used in the filter. For example: yellow, green, small, large. */
|
onClick={ removeCallback }
|
||||||
__(
|
>
|
||||||
'Remove %s filter',
|
{ removeText }
|
||||||
'woo-gutenberg-products-block'
|
|
||||||
),
|
|
||||||
name
|
|
||||||
) }
|
|
||||||
</button>
|
</button>
|
||||||
</span>
|
</span>
|
||||||
|
) }
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue