Skip to content

Commit 8a8d484

Browse files
richtaborgetdave
authored andcommitted
Revise LinkControl suggestions UI to use MenuItem (WordPress#50978)
* Use "link" instead of "URL" for URL_TYPE * Use MenuItem for search create button * Use sentence case for "Create page" * Use a MenuGroup for search results * Use MenuItem for search item * Refactoring styles (WIP) * Preserve whitespace in results text * Reinstate result item information including permalink * Remove debugging CSS code * Reinstate CSS to control size of rich previews favicon * Remove other commented out CSS code * Reinstate selected styles * Remove more redundant CSS * Add some basic results hover/focus styling. Needs improving * Improve icon alignment * Update tests to handle wording changes * Remove inconsistent hover/focus style MenuItem already has hover/focus styles * Reinstate is-selected visual state * Update test to make sense in context of WordPress#51011 See WordPress#51011 * Fix locator for result text --------- Co-authored-by: Dave Smith <getdavemail@gmail.com>
1 parent 04ddcbb commit 8a8d484

File tree

8 files changed

+140
-223
lines changed

8 files changed

+140
-223
lines changed

packages/block-editor/src/components/link-control/constants.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { __ } from '@wordpress/i18n';
88
// order to handle it as a unique case.
99
export const CREATE_TYPE = '__CREATE__';
1010
export const TEL_TYPE = 'tel';
11-
export const URL_TYPE = 'URL';
11+
export const URL_TYPE = 'link';
1212
export const MAILTO_TYPE = 'mailto';
1313
export const INTERNAL_TYPE = 'internal';
1414

packages/block-editor/src/components/link-control/search-create-button.js

+8-26
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,15 @@
1-
/**
2-
* External dependencies
3-
*/
4-
import classnames from 'classnames';
5-
61
/**
72
* WordPress dependencies
83
*/
94
import { __, sprintf } from '@wordpress/i18n';
10-
import { Button } from '@wordpress/components';
5+
import { MenuItem } from '@wordpress/components';
116
import { createInterpolateElement } from '@wordpress/element';
12-
import { Icon, plus } from '@wordpress/icons';
7+
import { plus } from '@wordpress/icons';
138

149
export const LinkControlSearchCreate = ( {
1510
searchTerm,
1611
onClick,
1712
itemProps,
18-
isSelected,
1913
buttonText,
2014
} ) => {
2115
if ( ! searchTerm ) {
@@ -40,27 +34,15 @@ export const LinkControlSearchCreate = ( {
4034
}
4135

4236
return (
43-
<Button
37+
<MenuItem
4438
{ ...itemProps }
45-
className={ classnames(
46-
'block-editor-link-control__search-create block-editor-link-control__search-item',
47-
{
48-
'is-selected': isSelected,
49-
}
50-
) }
39+
iconPosition="left"
40+
icon={ plus }
41+
className="block-editor-link-control__search-item"
5142
onClick={ onClick }
5243
>
53-
<Icon
54-
className="block-editor-link-control__search-item-icon"
55-
icon={ plus }
56-
/>
57-
58-
<span className="block-editor-link-control__search-item-header">
59-
<span className="block-editor-link-control__search-item-title">
60-
{ text }
61-
</span>
62-
</span>
63-
</Button>
44+
{ text }
45+
</MenuItem>
6446
);
6547
};
6648

packages/block-editor/src/components/link-control/search-item.js

+21-43
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
1-
/**
2-
* External dependencies
3-
*/
4-
import classnames from 'classnames';
5-
61
/**
72
* WordPress dependencies
83
*/
9-
import { safeDecodeURI, filterURLForDisplay } from '@wordpress/url';
104
import { __ } from '@wordpress/i18n';
11-
import { Button, TextHighlight } from '@wordpress/components';
5+
import { MenuItem, TextHighlight } from '@wordpress/components';
126
import {
137
Icon,
148
globe,
@@ -19,6 +13,7 @@ import {
1913
file,
2014
} from '@wordpress/icons';
2115
import { __unstableStripHTML as stripHTML } from '@wordpress/dom';
16+
import { safeDecodeURI, filterURLForDisplay } from '@wordpress/url';
2217

2318
const ICONS_MAP = {
2419
post: postList,
@@ -52,50 +47,33 @@ function SearchItemIcon( { isURL, suggestion } ) {
5247
export const LinkControlSearchItem = ( {
5348
itemProps,
5449
suggestion,
55-
isSelected = false,
50+
searchTerm,
5651
onClick,
5752
isURL = false,
58-
searchTerm = '',
5953
shouldShowType = false,
6054
} ) => {
55+
const info = isURL
56+
? __( 'Press ENTER to add this link' )
57+
: filterURLForDisplay( safeDecodeURI( suggestion?.url ) );
58+
6159
return (
62-
<Button
60+
<MenuItem
6361
{ ...itemProps }
62+
info={ info }
63+
iconPosition="left"
64+
icon={
65+
<SearchItemIcon suggestion={ suggestion } isURL={ isURL } />
66+
}
6467
onClick={ onClick }
65-
className={ classnames( 'block-editor-link-control__search-item', {
66-
'is-selected': isSelected,
67-
'is-url': isURL,
68-
'is-entity': ! isURL,
69-
} ) }
68+
shortcut={ shouldShowType && getVisualTypeName( suggestion ) }
69+
className="block-editor-link-control__search-item"
7070
>
71-
<SearchItemIcon suggestion={ suggestion } isURL={ isURL } />
72-
73-
<span className="block-editor-link-control__search-item-header">
74-
<span className="block-editor-link-control__search-item-title">
75-
<TextHighlight
76-
// The component expects a plain text string.
77-
text={ stripHTML( suggestion.title ) }
78-
highlight={ searchTerm }
79-
/>
80-
</span>
81-
<span
82-
aria-hidden={ ! isURL }
83-
className="block-editor-link-control__search-item-info"
84-
>
85-
{ ! isURL &&
86-
( filterURLForDisplay(
87-
safeDecodeURI( suggestion.url )
88-
) ||
89-
'' ) }
90-
{ isURL && __( 'Press ENTER to add this link' ) }
91-
</span>
92-
</span>
93-
{ shouldShowType && suggestion.type && (
94-
<span className="block-editor-link-control__search-item-type">
95-
{ getVisualTypeName( suggestion ) }
96-
</span>
97-
) }
98-
</Button>
71+
<TextHighlight
72+
// The component expects a plain text string.
73+
text={ stripHTML( suggestion.title ) }
74+
highlight={ searchTerm }
75+
/>
76+
</MenuItem>
9977
);
10078
};
10179

packages/block-editor/src/components/link-control/search-results.js

+48-46
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
* WordPress dependencies
33
*/
44
import { __, sprintf } from '@wordpress/i18n';
5-
import { VisuallyHidden } from '@wordpress/components';
5+
import { VisuallyHidden, MenuGroup } from '@wordpress/components';
66

77
/**
88
* External dependencies
@@ -72,59 +72,61 @@ export default function LinkControlSearchResults( {
7272
className={ resultsListClasses }
7373
aria-labelledby={ searchResultsLabelId }
7474
>
75-
{ suggestions.map( ( suggestion, index ) => {
76-
if (
77-
shouldShowCreateSuggestion &&
78-
CREATE_TYPE === suggestion.type
79-
) {
75+
<MenuGroup>
76+
{ suggestions.map( ( suggestion, index ) => {
77+
if (
78+
shouldShowCreateSuggestion &&
79+
CREATE_TYPE === suggestion.type
80+
) {
81+
return (
82+
<LinkControlSearchCreate
83+
searchTerm={ currentInputValue }
84+
buttonText={ createSuggestionButtonText }
85+
onClick={ () =>
86+
handleSuggestionClick( suggestion )
87+
}
88+
// Intentionally only using `type` here as
89+
// the constant is enough to uniquely
90+
// identify the single "CREATE" suggestion.
91+
key={ suggestion.type }
92+
itemProps={ buildSuggestionItemProps(
93+
suggestion,
94+
index
95+
) }
96+
isSelected={ index === selectedSuggestion }
97+
/>
98+
);
99+
}
100+
101+
// If we're not handling "Create" suggestions above then
102+
// we don't want them in the main results so exit early.
103+
if ( CREATE_TYPE === suggestion.type ) {
104+
return null;
105+
}
106+
80107
return (
81-
<LinkControlSearchCreate
82-
searchTerm={ currentInputValue }
83-
buttonText={ createSuggestionButtonText }
84-
onClick={ () =>
85-
handleSuggestionClick( suggestion )
86-
}
87-
// Intentionally only using `type` here as
88-
// the constant is enough to uniquely
89-
// identify the single "CREATE" suggestion.
90-
key={ suggestion.type }
108+
<LinkControlSearchItem
109+
key={ `${ suggestion.id }-${ suggestion.type }` }
91110
itemProps={ buildSuggestionItemProps(
92111
suggestion,
93112
index
94113
) }
114+
suggestion={ suggestion }
115+
index={ index }
116+
onClick={ () => {
117+
handleSuggestionClick( suggestion );
118+
} }
95119
isSelected={ index === selectedSuggestion }
120+
isURL={ LINK_ENTRY_TYPES.includes(
121+
suggestion.type
122+
) }
123+
searchTerm={ currentInputValue }
124+
shouldShowType={ shouldShowSuggestionsTypes }
125+
isFrontPage={ suggestion?.isFrontPage }
96126
/>
97127
);
98-
}
99-
100-
// If we're not handling "Create" suggestions above then
101-
// we don't want them in the main results so exit early.
102-
if ( CREATE_TYPE === suggestion.type ) {
103-
return null;
104-
}
105-
106-
return (
107-
<LinkControlSearchItem
108-
key={ `${ suggestion.id }-${ suggestion.type }` }
109-
itemProps={ buildSuggestionItemProps(
110-
suggestion,
111-
index
112-
) }
113-
suggestion={ suggestion }
114-
index={ index }
115-
onClick={ () => {
116-
handleSuggestionClick( suggestion );
117-
} }
118-
isSelected={ index === selectedSuggestion }
119-
isURL={ LINK_ENTRY_TYPES.includes(
120-
suggestion.type
121-
) }
122-
searchTerm={ currentInputValue }
123-
shouldShowType={ shouldShowSuggestionsTypes }
124-
isFrontPage={ suggestion?.isFrontPage }
125-
/>
126-
);
127-
} ) }
128+
} ) }
129+
</MenuGroup>
128130
</div>
129131
</div>
130132
);

0 commit comments

Comments
 (0)