diff --git a/packages/block-editor/src/components/link-control/index.js b/packages/block-editor/src/components/link-control/index.js
index c25ed5cd1187a8..412e10fa4d89b1 100644
--- a/packages/block-editor/src/components/link-control/index.js
+++ b/packages/block-editor/src/components/link-control/index.js
@@ -6,8 +6,14 @@ import classnames from 'classnames';
/**
* WordPress dependencies
*/
-import { Button, Spinner, Notice, TextControl } from '@wordpress/components';
-import { __ } from '@wordpress/i18n';
+import {
+ Button,
+ Spinner,
+ Notice,
+ TextControl,
+ VisuallyHidden,
+} from '@wordpress/components';
+import { __, sprintf } from '@wordpress/i18n';
import { useRef, useState, useEffect } from '@wordpress/element';
import { focus } from '@wordpress/dom';
import { ENTER } from '@wordpress/keycodes';
@@ -15,7 +21,8 @@ import { isShallowEqualObjects } from '@wordpress/is-shallow-equal';
import { useSelect, useDispatch } from '@wordpress/data';
import { store as preferencesStore } from '@wordpress/preferences';
import { keyboardReturn } from '@wordpress/icons';
-
+import { useInstanceId } from '@wordpress/compose';
+import { speak } from '@wordpress/a11y';
/**
* Internal dependencies
*/
@@ -201,11 +208,24 @@ function LinkControl( {
const { createPage, isCreatingPage, errorMessage } =
useCreatePage( createSuggestion );
+ function setEditingMode( nextEditingMode ) {
+ setIsEditingLink( nextEditingMode );
+
+ speak(
+ nextEditingMode
+ ? __( 'Entering link edit mode' )
+ : __( 'Leaving link edit mode' ),
+ 'assertive'
+ );
+ }
+
useEffect( () => {
if ( forceIsEditingLink === undefined ) {
return;
}
+ // Do not announcement automatic mode state change
+ // via speak().
setIsEditingLink( forceIsEditingLink );
}, [ forceIsEditingLink ] );
@@ -243,7 +263,7 @@ function LinkControl( {
wrapperNode.current.ownerDocument.activeElement
);
- setIsEditingLink( false );
+ setEditingMode( false );
};
const handleSelectSuggestion = ( updatedValue ) => {
@@ -335,23 +355,54 @@ function LinkControl( {
const showTextControl = hasLinkValue && hasTextControl;
const isEditing = ( isEditingLink || ! value ) && ! isCreatingPage;
+ const isCreating = isEditingLink && ! value && ! isCreatingPage;
const isDisabled = ! valueHasChanges || currentInputIsEmpty;
const showSettings = !! settings?.length && isEditingLink && hasLinkValue;
+ const dialogTitleId = useInstanceId(
+ LinkControl,
+ `block-editor-link-control___title`
+ );
+ const dialogDescritionId = useInstanceId(
+ LinkControl,
+ `block-editor-link-control___description`
+ );
+
+ const isPreviewing = value && ! isEditingLink && ! isCreatingPage;
return (
{ isCreatingPage && (
- { __( 'Creating' ) }…
+
+ { __( 'Creating' ) }…
) }
{ isEditing && (
<>
+
+
+ { sprintf(
+ // translators: %s: action name for the link mode (edit or create).
+ __( '%s Link' ),
+ isCreating ? __( 'Create' ) : __( 'Edit' )
+ ) }
+
+
+
+ { sprintf(
+ // translators: %s: action name for the link action (edit or create).
+ __( '%s the link' ),
+ isCreating ? __( 'Creating' ) : __( 'Editing' )
+ ) }
+
+
) }
- >
- ) }
- { value && ! isEditingLink && ! isCreatingPage && (
-
setIsEditingLink( true ) }
- hasRichPreviews={ hasRichPreviews }
- hasUnlinkControl={ shownUnlinkControl }
- additionalControls={ () => {
- // Expose the "Opens in new tab" settings in the preview
- // as it is the most common setting to change.
- if (
- settings?.find(
- ( setting ) => setting.id === 'opensInNewTab'
- )
- ) {
- return (
- id === 'opensInNewTab'
- ) }
- onChange={ onChange }
- />
- );
- }
- } }
- onRemove={ () => {
- onRemove();
- setIsEditingLink( true );
- } }
- />
- ) }
+ { showSettings && (
+
+ { ! currentInputIsEmpty && (
+
+
+
+ ) }
+
+ ) }
- { showSettings && (
-
- { ! currentInputIsEmpty && (
-
-
-
+ { showActions && (
+
+
+
+
) }
-
+ >
) }
- { showActions && (
-
-
-
-
+ { isPreviewing && (
+ <>
+
+ { __( 'Preview Link' ) }
+
+ { __( 'Previewing the currently selected link.' ) }
+
+
+ setEditingMode( true ) }
+ hasRichPreviews={ hasRichPreviews }
+ hasUnlinkControl={ shownUnlinkControl }
+ additionalControls={ () => {
+ // Expose the "Opens in new tab" settings in the preview
+ // as it is the most common setting to change.
+ if (
+ settings?.find(
+ ( setting ) =>
+ setting.id === 'opensInNewTab'
+ )
+ ) {
+ return (
+ id === 'opensInNewTab'
+ ) }
+ onChange={ onChange }
+ />
+ );
+ }
+ } }
+ onRemove={ () => {
+ onRemove();
+ setEditingMode( true );
+ } }
+ />
+ >
) }
{ renderControlBottom && renderControlBottom() }
diff --git a/packages/block-editor/src/components/link-control/link-preview.js b/packages/block-editor/src/components/link-control/link-preview.js
index 8272602cde908d..c9fc88fe9a1d1e 100644
--- a/packages/block-editor/src/components/link-control/link-preview.js
+++ b/packages/block-editor/src/components/link-control/link-preview.js
@@ -10,6 +10,7 @@ import { __ } from '@wordpress/i18n';
import {
Button,
ExternalLink,
+ VisuallyHidden,
__experimentalText as Text,
} from '@wordpress/components';
import { filterURLForDisplay, safeDecodeURI } from '@wordpress/url';
@@ -20,7 +21,6 @@ import { __unstableStripHTML as stripHTML } from '@wordpress/dom';
* Internal dependencies
*/
import { ViewerSlot } from './viewer-slot';
-
import useRichUrlData from './use-rich-url-data';
export default function LinkPreview( {
@@ -84,28 +84,43 @@ export default function LinkPreview( {
>
{ icon }
-
+
{ ! isEmptyURL ? (
<>
-
- { displayTitle }
-
+
+ - Link title
+
+ -
+
+ { displayTitle }
+
+
{ value?.url && displayTitle !== displayURL && (
-
- { displayURL }
-
+ <>
+
+ - Link URL
+
+ -
+ { displayURL }
+
+ >
) }
>
) : (
-
- { __( 'Link is empty' ) }
-
+ <>
+
+ - Link value
+
+ -
+ { __( 'Link is empty' ) }
+
+ >
) }
-
+