diff --git a/packages/base-styles/_z-index.scss b/packages/base-styles/_z-index.scss index 76cfad0b424a1..f5b6331e6fa58 100644 --- a/packages/base-styles/_z-index.scss +++ b/packages/base-styles/_z-index.scss @@ -18,6 +18,7 @@ $z-layers: ( ".block-editor-inserter__tabs .components-tab-panel__tab-content": 0, // lower scrolling content ".block-editor-inserter__tabs .components-tab-panel__tabs": 1, // higher sticky element ".block-editor-inserter__search": 1, // higher sticky element + ".block-library-template-part__selection-search": 1, // higher sticky element // These next two share a stacking context ".interface-complementary-area .components-panel" : 0, // lower scrolling content diff --git a/packages/block-library/src/template-part/edit/selection-modal.js b/packages/block-library/src/template-part/edit/selection-modal.js index a9e0ed68255ce..68a4c488fa875 100644 --- a/packages/block-library/src/template-part/edit/selection-modal.js +++ b/packages/block-library/src/template-part/edit/selection-modal.js @@ -1,7 +1,7 @@ /** * WordPress dependencies */ -import { useCallback, useMemo } from '@wordpress/element'; +import { useCallback, useMemo, useState } from '@wordpress/element'; import { __, sprintf } from '@wordpress/i18n'; import { store as noticesStore } from '@wordpress/notices'; import { useDispatch } from '@wordpress/data'; @@ -11,6 +11,10 @@ import { __experimentalBlockPatternsList as BlockPatternsList, store as blockEditorStore, } from '@wordpress/block-editor'; +import { + SearchControl, + __experimentalHStack as HStack, +} from '@wordpress/components'; /** * Internal dependencies @@ -21,6 +25,7 @@ import { useCreateTemplatePartFromBlocks, } from './utils/hooks'; import { createTemplatePartId } from './utils/create-template-part-id'; +import { searchPatterns } from './utils/search'; export default function TemplatePartSelectionModal( { setAttributes, @@ -29,6 +34,8 @@ export default function TemplatePartSelectionModal( { area, clientId, } ) { + const [ searchValue, setSearchValue ] = useState( '' ); + // When the templatePartId is undefined, // it means the user is creating a new one from the placeholder. const isReplacingTemplatePartContent = !! templatePartId; @@ -37,18 +44,24 @@ export default function TemplatePartSelectionModal( { templatePartId ); // We can map template parts to block patters to reuse the BlockPatternsList UI - const templartPartsAsBlockPatterns = useMemo( () => { - return templateParts.map( ( templatePart ) => ( { + const filteredTemplateParts = useMemo( () => { + const partsAsPatterns = templateParts.map( ( templatePart ) => ( { name: createTemplatePartId( templatePart.theme, templatePart.slug ), title: templatePart.title.rendered, blocks: parse( templatePart.content.raw ), templatePart, } ) ); - }, [ templateParts ] ); - const shownTemplateParts = useAsyncList( templartPartsAsBlockPatterns ); - const { createSuccessNotice } = useDispatch( noticesStore ); + + return searchPatterns( partsAsPatterns, searchValue ); + }, [ templateParts, searchValue ] ); + const shownTemplateParts = useAsyncList( filteredTemplateParts ); const blockPatterns = useAlternativeBlockPatterns( area, clientId ); - const shownBlockPatterns = useAsyncList( blockPatterns ); + const filteredBlockPatterns = useMemo( () => { + return searchPatterns( blockPatterns, searchValue ); + }, [ blockPatterns, searchValue ] ); + const shownBlockPatterns = useAsyncList( filteredBlockPatterns ); + + const { createSuccessNotice } = useDispatch( noticesStore ); const { replaceInnerBlocks } = useDispatch( blockEditorStore ); const onTemplatePartSelect = useCallback( ( templatePart ) => { @@ -75,41 +88,56 @@ export default function TemplatePartSelectionModal( { setAttributes ); + const hasTemplateParts = !! filteredTemplateParts.length; + const hasBlockPatterns = !! filteredBlockPatterns.length; + return ( - <> -
{ __( 'No results found.' ) }
+