diff --git a/packages/editor/src/components/url-input/index.js b/packages/editor/src/components/url-input/index.js index 23762991cddcff..c841d1acf35991 100644 --- a/packages/editor/src/components/url-input/index.js +++ b/packages/editor/src/components/url-input/index.js @@ -11,7 +11,7 @@ import scrollIntoView from 'dom-scroll-into-view'; import { __, sprintf, _n } from '@wordpress/i18n'; import { Component, Fragment, createRef } from '@wordpress/element'; import { decodeEntities } from '@wordpress/html-entities'; -import { UP, DOWN, ENTER } from '@wordpress/keycodes'; +import { UP, DOWN, ENTER, TAB } from '@wordpress/keycodes'; import { Spinner, withSpokenMessages, Popover } from '@wordpress/components'; import { withInstanceId } from '@wordpress/compose'; import apiFetch from '@wordpress/api-fetch'; @@ -29,6 +29,7 @@ class URLInput extends Component { this.onChange = this.onChange.bind( this ); this.onKeyDown = this.onKeyDown.bind( this ); this.autocompleteRef = autocompleteRef || createRef(); + this.inputRef = createRef(); this.updateSuggestions = throttle( this.updateSuggestions.bind( this ), 200 ); this.suggestionNodes = []; @@ -140,6 +141,8 @@ class URLInput extends Component { return; } + const post = this.state.posts[ this.state.selectedSuggestion ]; + switch ( event.keyCode ) { case UP: { event.stopPropagation(); @@ -159,12 +162,20 @@ class URLInput extends Component { } ); break; } + case TAB: { + if ( this.state.selectedSuggestion !== null ) { + this.selectLink( post ); + // Announce a link has been selected when tabbing away from the input field. + this.props.speak( __( 'Link selected' ) ); + } + break; + } case ENTER: { if ( this.state.selectedSuggestion !== null ) { event.stopPropagation(); - const post = this.state.posts[ this.state.selectedSuggestion ]; this.selectLink( post ); } + break; } } } @@ -177,6 +188,12 @@ class URLInput extends Component { } ); } + handleOnClick( post ) { + this.selectLink( post ); + // Move focus to the input field when a link suggestion is clicked. + this.inputRef.current.focus(); + } + render() { const { value = '', autoFocus = true, instanceId } = this.props; const { showSuggestions, posts, selectedSuggestion, loading } = this.state; @@ -199,6 +216,7 @@ class URLInput extends Component { aria-autocomplete="list" aria-owns={ `editor-url-input-suggestions-${ instanceId }` } aria-activedescendant={ selectedSuggestion !== null ? `editor-url-input-suggestion-${ instanceId }-${ selectedSuggestion }` : undefined } + ref={ this.inputRef } /> { ( loading ) && } @@ -222,7 +240,7 @@ class URLInput extends Component { className={ classnames( 'editor-url-input__suggestion', { 'is-selected': index === selectedSuggestion, } ) } - onClick={ () => this.selectLink( post ) } + onClick={ () => this.handleOnClick( post ) } aria-selected={ index === selectedSuggestion } > { decodeEntities( post.title ) || __( '(no title)' ) } diff --git a/packages/editor/src/components/url-input/style.scss b/packages/editor/src/components/url-input/style.scss index 3fe564178d683a..0946802bcbd059 100644 --- a/packages/editor/src/components/url-input/style.scss +++ b/packages/editor/src/components/url-input/style.scss @@ -1,11 +1,10 @@ // Link input -$input-padding: 9px 8px; +$input-padding: 8px; $input-size: 300px; .editor-block-list__block .editor-url-input, .components-popover .editor-url-input, .editor-url-input { - width: 100%; flex-grow: 1; position: relative; padding: 1px; @@ -28,8 +27,8 @@ $input-size: 300px; .components-spinner { position: absolute; - right: 0; - top: $input-padding; + right: $input-padding; + top: $input-padding + 1; margin: 0; } } @@ -38,9 +37,10 @@ $input-size: 300px; .editor-url-input__suggestions { max-height: 200px; transition: all 0.15s ease-in-out; - list-style: none; padding: 4px 0; - width: $input-size + 2 * $icon-button-size; + // To match the url-input width: input width + padding + 2 buttons. + width: $input-size + 2 + 2 * $icon-button-size; + overflow-y: auto; } // Hide suggestions on mobile until we @todo find a better way to show them @@ -53,7 +53,7 @@ $input-size: 300px; } .editor-url-input__suggestion { - padding: 4px #{ $icon-button-size + $input-padding } 4px $input-padding; + padding: 4px $input-padding; color: $dark-gray-300; // lightest we can use for contrast display: block; font-size: $default-font-size; diff --git a/packages/format-library/src/link/inline.js b/packages/format-library/src/link/inline.js index 95fb1eb4045252..ef3ec4513adb53 100644 --- a/packages/format-library/src/link/inline.js +++ b/packages/format-library/src/link/inline.js @@ -179,9 +179,9 @@ class InlineLinkUI extends Component { this.resetState(); if ( isActive ) { - speak( __( 'Link edited.' ), 'assertive' ); + speak( __( 'Link edited' ), 'assertive' ); } else { - speak( __( 'Link added.' ), 'assertive' ); + speak( __( 'Link inserted' ), 'assertive' ); } }