Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
10 changes: 8 additions & 2 deletions blocks/editable/format-toolbar/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { isUndefined } from 'lodash';
*/
import { __ } from '@wordpress/i18n';
import { Component } from '@wordpress/element';
import { IconButton, Toolbar } from '@wordpress/components';
import { IconButton, Toolbar, withA11yMessages } from '@wordpress/components';
import { keycodes } from '@wordpress/utils';

/**
Expand Down Expand Up @@ -125,6 +125,12 @@ class FormatToolbar extends Component {
this.setState( {
isEditingLink: false,
} );
if (
this.props.formats.link.value === '' &&
!! this.state.linkValue.length
) {
this.props.speak( __( 'Link inserted.' ), 'assertive' );
}
}

updateLinkValue( linkValue ) {
Expand Down Expand Up @@ -187,4 +193,4 @@ class FormatToolbar extends Component {
}
}

export default FormatToolbar;
export default withA11yMessages( FormatToolbar );
18 changes: 6 additions & 12 deletions blocks/url-input/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { throttle, debounce } from 'lodash';
import { throttle } from 'lodash';
import classnames from 'classnames';
import scrollIntoView from 'dom-scroll-into-view';

Expand All @@ -11,7 +11,7 @@ import scrollIntoView from 'dom-scroll-into-view';
import { __, sprintf, _n } from '@wordpress/i18n';
import { Component } from '@wordpress/element';
import { keycodes } from '@wordpress/utils';
import { Spinner, withInstanceId } from '@wordpress/components';
import { Spinner, withInstanceId, withA11yMessages } from '@wordpress/components';

const { UP, DOWN, ENTER } = keycodes;

Expand All @@ -22,7 +22,6 @@ class UrlInput extends Component {
this.onKeyDown = this.onKeyDown.bind( this );
this.bindListNode = this.bindListNode.bind( this );
this.updateSuggestions = throttle( this.updateSuggestions.bind( this ), 200 );
this.debouncedSpeakAssertive = debounce( this.speakAssertive.bind( this ), 500 );
this.suggestionNodes = [];
this.state = {
posts: [],
Expand Down Expand Up @@ -77,13 +76,13 @@ class UrlInput extends Component {
} );

if ( !! posts.length ) {
this.debouncedSpeakAssertive( sprintf( _n(
this.props.debouncedSpeak( sprintf( _n(
'%d result found, use up and down arrow keys to navigate.',
'%d results found, use up and down arrow keys to navigate.',
posts.length
), posts.length ) );
), posts.length ), 'assertive' );
} else {
this.debouncedSpeakAssertive( __( 'No results.' ) );
this.props.debouncedSpeak( __( 'No results.' ), 'assertive' );
}
},
( xhr ) => {
Expand Down Expand Up @@ -137,15 +136,10 @@ class UrlInput extends Component {
}
}

speakAssertive( message ) {
wp.a11y.speak( message, 'assertive' );
}

componentWillUnmount() {
if ( this.suggestionsRequest ) {
this.suggestionsRequest.abort();
}
this.debouncedSpeakAssertive.cancel();
}

componentDidUpdate() {
Expand Down Expand Up @@ -220,4 +214,4 @@ class UrlInput extends Component {
}
}

export default withInstanceId( UrlInput );
export default withA11yMessages( withInstanceId( UrlInput ) );
24 changes: 8 additions & 16 deletions components/form-token-field/index.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
* External dependencies
*/
import { last, take, clone, uniq, map, difference, each, identity, some, debounce } from 'lodash';
import { last, take, clone, uniq, map, difference, each, identity, some } from 'lodash';
import classnames from 'classnames';

/**
Expand All @@ -18,6 +18,7 @@ import Token from './token';
import TokenInput from './token-input';
import SuggestionsList from './suggestions-list';
import withInstanceId from '../higher-order/with-instance-id';
import withA11yMessages from '../higher-order/with-a11y-messages';

const initialState = {
incompleteTokenValue: '',
Expand Down Expand Up @@ -46,7 +47,6 @@ class FormTokenField extends Component {
this.onInputChange = this.onInputChange.bind( this );
this.bindInput = this.bindInput.bind( this );
this.bindTokensAndInput = this.bindTokensAndInput.bind( this );
this.debouncedSpeakAssertive = debounce( this.speakAssertive.bind( this ), 500 );
}

componentDidUpdate() {
Expand All @@ -64,10 +64,6 @@ class FormTokenField extends Component {
}
}

componentWillUnmount() {
this.debouncedSpeakAssertive.cancel();
}

bindInput( ref ) {
this.input = ref;
}
Expand Down Expand Up @@ -197,13 +193,13 @@ class FormTokenField extends Component {
if ( showMessage ) {
const matchingSuggestions = this.getMatchingSuggestions( tokenValue );
if ( !! matchingSuggestions.length ) {
this.debouncedSpeakAssertive( sprintf( _n(
this.props.debouncedSpeak( sprintf( _n(
'%d result found, use up and down arrow keys to navigate.',
'%d results found, use up and down arrow keys to navigate.',
matchingSuggestions.length
), matchingSuggestions.length ) );
), matchingSuggestions.length ), 'assertive' );
} else {
this.debouncedSpeakAssertive( __( 'No results.' ) );
this.props.debouncedSpeak( __( 'No results.' ), 'assertive' );
}
}
}
Expand Down Expand Up @@ -344,7 +340,7 @@ class FormTokenField extends Component {

addNewToken( token ) {
this.addNewTokens( [ token ] );
this.speakAssertive( this.props.messages.added );
this.props.speak( this.props.messages.added, 'assertive' );

this.setState( {
incompleteTokenValue: '',
Expand All @@ -362,7 +358,7 @@ class FormTokenField extends Component {
return this.getTokenValue( item ) !== this.getTokenValue( token );
} );
this.props.onChange( newTokens );
this.speakAssertive( this.props.messages.removed );
this.props.speak( this.props.messages.removed, 'assertive' );
}

getTokenValue( token ) {
Expand Down Expand Up @@ -406,10 +402,6 @@ class FormTokenField extends Component {
return take( suggestions, maxSuggestions );
}

speakAssertive( message ) {
wp.a11y.speak( message, 'assertive' );
}

getSelectedSuggestion() {
if ( this.state.selectedSuggestionIndex !== -1 ) {
return this.getMatchingSuggestions()[ this.state.selectedSuggestionIndex ];
Expand Down Expand Up @@ -572,4 +564,4 @@ FormTokenField.defaultProps = {
},
};

export default withInstanceId( FormTokenField );
export default withA11yMessages( withInstanceId( FormTokenField ) );
44 changes: 44 additions & 0 deletions components/higher-order/with-a11y-messages/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/**
* External dependencies
*/
import { debounce } from 'lodash';

/**
* WordPress dependencies
*/
import { Component } from 'element';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note with #2172, these need to be updated to prefix the dependencies with @wordpress/. You will need to perform a rebase against the latest version of master and apply your changes:

git fetch origin
git rebase origin/master


/**
* A Higher Order Component used to be provide a unique instance ID by component
*
* @param {WPElement} WrappedComponent The wrapped component
*
* @return {Component} Component with an instanceId prop.
*/
function withA11yMessages( WrappedComponent ) {
return class extends Component {
constructor() {
super( ...arguments );
this.debouncedSpeak = debounce( this.speak.bind( this ), 500 );
}

speak( message, type = 'polite' ) {
wp.a11y.speak( message, type );
}

componentWillUnmount() {
this.debouncedSpeak.cancel();
}

render() {
return (
<WrappedComponent { ...this.props }
speak={ this.speak }
debouncedSpeak={ this.debouncedSpeak }
/>
);
}
};
}

export default withA11yMessages;
27 changes: 27 additions & 0 deletions components/higher-order/with-a11y-messages/test/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* External dependencies
*/
import { render } from 'enzyme';
import { isFunction } from 'lodash';

/**
* Internal dependencies
*/
import withA11yMessages from '../';

describe( 'withA11yMessages', () => {
it( 'should generate speak and debouncedSpeak props', () => {
const testSpeak = jest.fn();
const testDebouncedSpeak = jest.fn();
const DumpComponent = withA11yMessages( ( { speak, debouncedSpeak } ) => {
testSpeak( isFunction( speak ) );
testDebouncedSpeak( isFunction( debouncedSpeak ) );
return <div />;
} );
render( <DumpComponent /> );

// Unrendered element.
expect( testSpeak ).toBeCalledWith( true );
expect( testDebouncedSpeak ).toBeCalledWith( true );
} );
} );
1 change: 1 addition & 0 deletions components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@ export { default as Popover } from './popover';
// Higher-Order Components
export { default as withFocusReturn } from './higher-order/with-focus-return';
export { default as withInstanceId } from './higher-order/with-instance-id';
export { default as withA11yMessages } from './higher-order/with-a11y-messages';
14 changes: 6 additions & 8 deletions editor/inserter/menu.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
/**
* External dependencies
*/
import { flow, groupBy, sortBy, findIndex, filter, debounce, find, some } from 'lodash';
import { flow, groupBy, sortBy, findIndex, filter, find, some } from 'lodash';
import { connect } from 'react-redux';

/**
* WordPress dependencies
*/
import { __, _n, sprintf } from '@wordpress/i18n';
import { Component } from '@wordpress/element';
import { Popover, withFocusReturn, withInstanceId } from '@wordpress/components';
import { Popover, withFocusReturn, withInstanceId, withA11yMessages } from '@wordpress/components';
import { keycodes } from '@wordpress/utils';
import { getCategories, getBlockTypes, BlockIcon } from '@wordpress/blocks';

Expand Down Expand Up @@ -47,8 +47,6 @@ export class InserterMenu extends Component {
this.getBlocksForCurrentTab = this.getBlocksForCurrentTab.bind( this );
this.sortBlocks = this.sortBlocks.bind( this );
this.addRecentBlocks = this.addRecentBlocks.bind( this );
const speakAssertive = ( message ) => wp.a11y.speak( message, 'assertive' );
this.debouncedSpeakAssertive = debounce( speakAssertive, 500 );
}

componentDidMount() {
Expand All @@ -57,20 +55,19 @@ export class InserterMenu extends Component {

componentWillUnmount() {
document.removeEventListener( 'keydown', this.onKeyDown );
this.debouncedSpeakAssertive.cancel();
}

componentDidUpdate() {
const searchResults = this.searchBlocks( getBlockTypes() );
// Announce the blocks search results to screen readers.
if ( !! searchResults.length ) {
this.debouncedSpeakAssertive( sprintf( _n(
this.props.debouncedSpeak( sprintf( _n(
'%d result found',
'%d results found',
searchResults.length
), searchResults.length ) );
), searchResults.length ), 'assertive' );
} else {
this.debouncedSpeakAssertive( __( 'No results.' ) );
this.props.debouncedSpeak( __( 'No results.' ), 'assertive' );
}
}

Expand Down Expand Up @@ -443,6 +440,7 @@ const connectComponent = connect(

export default flow(
withInstanceId,
withA11yMessages,
withFocusReturn,
connectComponent
)( InserterMenu );
7 changes: 7 additions & 0 deletions editor/inserter/test/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ describe( 'InserterMenu', () => {
instanceId={ 1 }
blocks={ [] }
recentlyUsedBlocks={ [] }
debouncedSpeak={ noop }
/>
);

Expand All @@ -107,6 +108,7 @@ describe( 'InserterMenu', () => {
instanceId={ 1 }
blocks={ [] }
recentlyUsedBlocks={ [ advancedTextBlock ] }
debouncedSpeak={ noop }
/>
);

Expand All @@ -122,6 +124,7 @@ describe( 'InserterMenu', () => {
instanceId={ 1 }
blocks={ [] }
recentlyUsedBlocks={ [] }
debouncedSpeak={ noop }
/>
);
const embedTab = wrapper.find( '.editor-inserter__tab' )
Expand All @@ -143,6 +146,7 @@ describe( 'InserterMenu', () => {
instanceId={ 1 }
blocks={ [] }
recentlyUsedBlocks={ [] }
debouncedSpeak={ noop }
/>
);
const blocksTab = wrapper.find( '.editor-inserter__tab' )
Expand All @@ -166,6 +170,7 @@ describe( 'InserterMenu', () => {
instanceId={ 1 }
blocks={ [ { name: moreBlock.name } ] }
recentlyUsedBlocks={ [] }
debouncedSpeak={ noop }
/>
);
const blocksTab = wrapper.find( '.editor-inserter__tab' )
Expand All @@ -183,6 +188,7 @@ describe( 'InserterMenu', () => {
instanceId={ 1 }
blocks={ [] }
recentlyUsedBlocks={ [] }
debouncedSpeak={ noop }
/>
);
wrapper.setState( { filterValue: 'text' } );
Expand All @@ -203,6 +209,7 @@ describe( 'InserterMenu', () => {
instanceId={ 1 }
blocks={ [] }
recentlyUsedBlocks={ [] }
debouncedSpeak={ noop }
/>
);
wrapper.setState( { filterValue: ' text' } );
Expand Down