diff --git a/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/template-parts.js b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/template-parts.js
index ad597671aba41..c2d8a919714d9 100644
--- a/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/template-parts.js
+++ b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/template-parts.js
@@ -9,17 +9,24 @@ import { map } from 'lodash';
import { __ } from '@wordpress/i18n';
import { useSelect } from '@wordpress/data';
import {
- __experimentalNavigationItem as NavigationItem,
__experimentalNavigationMenu as NavigationMenu,
+ __experimentalNavigationItem as NavigationItem,
} from '@wordpress/components';
+import { useState, useCallback } from '@wordpress/element';
/**
* Internal dependencies
*/
import TemplateNavigationItem from '../template-navigation-item';
import { MENU_ROOT, MENU_TEMPLATE_PARTS } from '../constants';
+import SearchResults from '../search-results';
export default function TemplatePartsMenu() {
+ const [ search, setSearch ] = useState( '' );
+ const onSearch = useCallback( ( value ) => {
+ setSearch( value );
+ } );
+
const templateParts = useSelect( ( select ) => {
const unfilteredTemplateParts =
select( 'core' ).getEntityRecords( 'postType', 'wp_template_part', {
@@ -38,15 +45,25 @@ export default function TemplatePartsMenu() {
menu={ MENU_TEMPLATE_PARTS }
title={ __( 'Template Parts' ) }
parentMenu={ MENU_ROOT }
+ hasSearch={ true }
+ onSearch={ onSearch }
+ search={ search }
>
- { map( templateParts, ( templatePart ) => (
-
- ) ) }
+ { search && (
+
+ ) }
+
+ { ! search &&
+ map( templateParts, ( templatePart ) => (
+
+ ) ) }
- { ! templateParts && }
+ { ! search && templateParts === null && (
+
+ ) }
);
}
diff --git a/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/templates.js b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/templates.js
index e96aaef7f8d99..c3f15d44d10ed 100644
--- a/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/templates.js
+++ b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/menus/templates.js
@@ -12,6 +12,7 @@ import {
} from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import { __, _x } from '@wordpress/i18n';
+import { useState, useCallback } from '@wordpress/element';
/**
* Internal dependencies
@@ -30,8 +31,14 @@ import {
import TemplatesAllMenu from './templates-all';
import NewTemplateDropdown from '../new-template-dropdown';
import TemplateNavigationItem from '../template-navigation-item';
+import SearchResults from '../search-results';
export default function TemplatesMenu() {
+ const [ search, setSearch ] = useState( '' );
+ const onSearch = useCallback( ( value ) => {
+ setSearch( value );
+ } );
+
const templates = useSelect(
( select ) =>
select( 'core' ).getEntityRecords( 'postType', 'wp_template', {
@@ -51,27 +58,43 @@ export default function TemplatesMenu() {
title={ __( 'Templates' ) }
titleAction={ }
parentMenu={ MENU_ROOT }
+ hasSearch={ true }
+ onSearch={ onSearch }
+ search={ search }
>
- { map( generalTemplates, ( template ) => (
-
- ) ) }
-
-
-
+ { search && (
+
+ ) }
+
+ { ! search && (
+ <>
+
+
+
+ { map( generalTemplates, ( template ) => (
+
+ ) ) }
+ >
+ ) }
+
+ { ! search && templates === null && (
+
+ ) }
+
diff --git a/packages/edit-site/src/components/navigation-sidebar/navigation-panel/search-results.js b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/search-results.js
new file mode 100644
index 0000000000000..39e7b60cb1781
--- /dev/null
+++ b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/search-results.js
@@ -0,0 +1,73 @@
+/**
+ * External dependencies
+ */
+import { map } from 'lodash';
+
+/**
+ * WordPress dependencies
+ */
+import { useMemo } from '@wordpress/element';
+import { __experimentalNavigationGroup as NavigationGroup } from '@wordpress/components';
+import { __ } from '@wordpress/i18n';
+
+/**
+ * Internal dependencies
+ */
+import { normalizedSearch } from './utils';
+import { useSelect } from '@wordpress/data';
+import TemplateNavigationItem from './template-navigation-item';
+
+export default function SearchResults( { items, search } ) {
+ const itemType = items?.length > 0 ? items[ 0 ].type : null;
+
+ const itemInfos = useSelect(
+ ( select ) => {
+ if ( itemType === 'wp_template' ) {
+ const {
+ __experimentalGetTemplateInfo: getTemplateInfo,
+ } = select( 'core/editor' );
+
+ return items.map( ( item ) => ( {
+ slug: item.slug,
+ ...getTemplateInfo( item ),
+ } ) );
+ }
+
+ return items.map( ( item ) => ( {
+ slug: item.slug,
+ title: item.title?.rendered,
+ description: item.excerpt?.rendered,
+ } ) );
+ },
+ [ items, itemType ]
+ );
+
+ const itemsFiltered = useMemo( () => {
+ if ( items === null || search.length === 0 ) {
+ return [];
+ }
+
+ return items.filter( ( { slug } ) => {
+ const { title, description } = itemInfos.find(
+ ( info ) => info.slug === slug
+ );
+
+ return (
+ normalizedSearch( slug, search ) ||
+ normalizedSearch( title, search ) ||
+ normalizedSearch( description, search )
+ );
+ } );
+ }, [ items, itemInfos, search ] );
+
+ return (
+
+ { map( itemsFiltered, ( item ) => (
+
+ ) ) }
+
+ );
+}
diff --git a/packages/edit-site/src/components/navigation-sidebar/navigation-panel/style.scss b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/style.scss
index b8c982265b9cb..d4fe4b544deca 100644
--- a/packages/edit-site/src/components/navigation-sidebar/navigation-panel/style.scss
+++ b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/style.scss
@@ -114,7 +114,6 @@
}
.edit-site-navigation-panel__new-template-dropdown {
- display: flex;
margin: 0 0 0 $grid-unit-15;
button {
diff --git a/packages/edit-site/src/components/navigation-sidebar/navigation-panel/utils.js b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/utils.js
new file mode 100644
index 0000000000000..251b90cfe44df
--- /dev/null
+++ b/packages/edit-site/src/components/navigation-sidebar/navigation-panel/utils.js
@@ -0,0 +1,11 @@
+/**
+ * External dependencies
+ */
+import { deburr } from 'lodash';
+
+// @see packages/block-editor/src/components/inserter/search-items.js
+export const normalizeInput = ( input ) =>
+ deburr( input ).replace( /^\//, '' ).toLowerCase();
+
+export const normalizedSearch = ( title, search ) =>
+ -1 !== normalizeInput( title ).indexOf( normalizeInput( search ) );