diff --git a/packages/block-editor/src/components/link-control/index.js b/packages/block-editor/src/components/link-control/index.js index 6be843ea5b4b4..2d7b850e552fc 100644 --- a/packages/block-editor/src/components/link-control/index.js +++ b/packages/block-editor/src/components/link-control/index.js @@ -7,8 +7,8 @@ import { noop, startsWith } from 'lodash'; /** * WordPress dependencies */ -import { Button, ExternalLink } from '@wordpress/components'; -import { __ } from '@wordpress/i18n'; +import { Button, ExternalLink, VisuallyHidden } from '@wordpress/components'; +import { __, sprintf } from '@wordpress/i18n'; import { useCallback, useState, Fragment } from '@wordpress/element'; import { @@ -131,16 +131,29 @@ export function LinkControl( { }, [ handleDirectEntry, fetchSearchSuggestions ] ); // Render Components - const renderSearchResults = ( { suggestionsListProps, buildSuggestionItemProps, suggestions, selectedSuggestion, isLoading } ) => { + const renderSearchResults = ( { suggestionsListProps, buildSuggestionItemProps, suggestions, selectedSuggestion, isLoading, isInitialSuggestions } ) => { const resultsListClasses = classnames( 'block-editor-link-control__search-results', { 'is-loading': isLoading, } ); const manualLinkEntryTypes = [ 'url', 'mailto', 'tel', 'internal' ]; + const searchResultsLabelId = isInitialSuggestions ? `block-editor-link-control-search-results-label-${ instanceId }` : undefined; + const labelText = isInitialSuggestions ? __( 'Recently updated' ) : sprintf( __( 'Search results for %s' ), inputValue ); + // According to guidelines aria-label should be added if the label + // itself is not visible. + // See: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Roles/listbox_role + const ariaLabel = isInitialSuggestions ? undefined : labelText; + const SearchResultsLabel = ( + + { labelText } + + ); return (
-
+ { isInitialSuggestions ? SearchResultsLabel : { SearchResultsLabel } } + +
{ suggestions.map( ( suggestion, index ) => ( { const searchInput = container.querySelector( 'input[aria-label="URL"]' ); // TODO: select these by aria relationship to autocomplete rather than arbitary selector. - const initialSearchResultElements = container.querySelectorAll( '[role="listbox"] [role="option"]' ); + const searchResultsWrapper = container.querySelector( '[role="listbox"]' ); + const initialSearchResultElements = searchResultsWrapper.querySelectorAll( '[role="option"]' ); + + const searchResultsLabel = container.querySelector( `#${ searchResultsWrapper.getAttribute( 'aria-labelledby' ) }` ); // Verify input has no value has default suggestions should only show // when this does not have a value @@ -342,6 +345,8 @@ describe( 'Default search suggestions', () => { // Verify the search results already display the initial suggestions expect( initialSearchResultElements ).toHaveLength( expectedResultsLength ); + + expect( searchResultsLabel.innerHTML ).toEqual( 'Recently updated' ); } ); it( 'should not display initial suggestions when input value is present', async () => { diff --git a/packages/block-editor/src/components/url-input/index.js b/packages/block-editor/src/components/url-input/index.js index 34f934a9cd2fd..3f4d6d4e40e13 100644 --- a/packages/block-editor/src/components/url-input/index.js +++ b/packages/block-editor/src/components/url-input/index.js @@ -298,6 +298,7 @@ class URLInput extends Component { placeholder = __( 'Paste URL or type to search' ), value = '', autoFocus = true, + __experimentalShowInitialSuggestions = false, } = this.props; const { @@ -365,6 +366,7 @@ class URLInput extends Component { buildSuggestionItemProps, isLoading: loading, handleSuggestionClick: this.handleOnClick, + isInitialSuggestions: __experimentalShowInitialSuggestions && ! ( value && value.length ), } ) } { ! isFunction( renderSuggestions ) && showSuggestions && !! suggestions.length &&