NumberFilter: a11y speak a description of the filter once all inputs are populated.
This commit is contained in:
parent
cbc5bc36fd
commit
7663cb2881
|
@ -3,7 +3,7 @@
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
import { Component, Fragment } from '@wordpress/element';
|
import { Component, Fragment } from '@wordpress/element';
|
||||||
import { SelectControl, TextControl } from '@wordpress/components';
|
import { withSpokenMessages, SelectControl, TextControl } from '@wordpress/components';
|
||||||
import { get, find, partial } from 'lodash';
|
import { get, find, partial } from 'lodash';
|
||||||
import interpolateComponents from 'interpolate-components';
|
import interpolateComponents from 'interpolate-components';
|
||||||
import classnames from 'classnames';
|
import classnames from 'classnames';
|
||||||
|
@ -14,18 +14,33 @@ import { sprintf, __, _x } from '@wordpress/i18n';
|
||||||
*/
|
*/
|
||||||
import TextControlWithAffixes from '../../text-control-with-affixes';
|
import TextControlWithAffixes from '../../text-control-with-affixes';
|
||||||
import { formatCurrency } from '@woocommerce/currency';
|
import { formatCurrency } from '@woocommerce/currency';
|
||||||
import { ariaHideStrings } from './utils';
|
import { ariaHideStrings, textContent } from './utils';
|
||||||
|
|
||||||
class NumberFilter extends Component {
|
class NumberFilter extends Component {
|
||||||
|
componentDidUpdate() {
|
||||||
|
const { config, debouncedSpeak, filter } = this.props;
|
||||||
|
const [ rangeStart, rangeEnd ] = ( filter.value || '' ).split( ',' );
|
||||||
|
|
||||||
|
if ( 'between' === filter.rule && ( ! rangeStart || ! rangeEnd ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! rangeStart ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
debouncedSpeak( this.getScreenReaderText( filter, config ) );
|
||||||
|
}
|
||||||
|
|
||||||
getBetweenString() {
|
getBetweenString() {
|
||||||
return _x(
|
return _x(
|
||||||
'{{rangeStart /}}{{span}}and{{/span}}{{rangeEnd /}}',
|
'{{rangeStart /}}{{span}} and {{/span}}{{rangeEnd /}}',
|
||||||
'Numerical range inputs arranged on a single line',
|
'Numerical range inputs arranged on a single line',
|
||||||
'wc-admin'
|
'wc-admin'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
getLegend( filter, config ) {
|
getScreenReaderText( filter, config ) {
|
||||||
const inputType = get( config, [ 'input', 'type' ], 'number' );
|
const inputType = get( config, [ 'input', 'type' ], 'number' );
|
||||||
const rule = find( config.rules, { value: filter.rule } ) || {};
|
const rule = find( config.rules, { value: filter.rule } ) || {};
|
||||||
let [ rangeStart, rangeEnd ] = ( filter.value || '' ).split( ',' );
|
let [ rangeStart, rangeEnd ] = ( filter.value || '' ).split( ',' );
|
||||||
|
@ -35,7 +50,7 @@ class NumberFilter extends Component {
|
||||||
! rangeStart ||
|
! rangeStart ||
|
||||||
( 'between' === rule.value && ! rangeEnd )
|
( 'between' === rule.value && ! rangeEnd )
|
||||||
) {
|
) {
|
||||||
return get( config, [ 'labels', 'add' ] );
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( 'currency' === inputType ) {
|
if ( 'currency' === inputType ) {
|
||||||
|
@ -56,13 +71,13 @@ class NumberFilter extends Component {
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
return interpolateComponents( {
|
return textContent( interpolateComponents( {
|
||||||
mixedString: config.labels.title,
|
mixedString: config.labels.title,
|
||||||
components: {
|
components: {
|
||||||
filter: <span>{ filterStr }</span>,
|
filter: <Fragment>{ filterStr }</Fragment>,
|
||||||
rule: <span>{ rule.label }</span>,
|
rule: <Fragment>{ rule.label }</Fragment>,
|
||||||
},
|
},
|
||||||
} );
|
} ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
getFormControl( { type, value, label, onChange } ) {
|
getFormControl( { type, value, label, onChange } ) {
|
||||||
|
@ -229,4 +244,4 @@ class NumberFilter extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default NumberFilter;
|
export default withSpokenMessages( NumberFilter );
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* External dependencies
|
* External dependencies
|
||||||
*/
|
*/
|
||||||
import { isArray, isString } from 'lodash';
|
import { isArray, isNumber, isString } from 'lodash';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hide all bare strings from the accessibility tree.
|
* Hide all bare strings from the accessibility tree.
|
||||||
|
@ -22,3 +22,35 @@ export function ariaHideStrings( components ) {
|
||||||
: component
|
: component
|
||||||
) );
|
) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* DOM Node.textContent for React components
|
||||||
|
* See: https://github.com/rwu823/react-addons-text-content/blob/master/src/index.js
|
||||||
|
*
|
||||||
|
* @param {Array<string|ReactNode>} components array of components
|
||||||
|
*
|
||||||
|
* @returns {string} concatenated text content of all nodes
|
||||||
|
*/
|
||||||
|
export function textContent( components ) {
|
||||||
|
let text = '';
|
||||||
|
|
||||||
|
const toText = ( component ) => {
|
||||||
|
if ( isString( component ) || isNumber( component ) ) {
|
||||||
|
text += component;
|
||||||
|
} else if ( isArray( component ) ) {
|
||||||
|
component.forEach( toText );
|
||||||
|
} else if ( component && component.props ) {
|
||||||
|
const { children } = component.props;
|
||||||
|
|
||||||
|
if ( isArray( children ) ) {
|
||||||
|
children.forEach( toText );
|
||||||
|
} else {
|
||||||
|
toText( children );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
toText( components );
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue