Skip to content

Commit

Permalink
Move search into inserter tabs (#61108)
Browse files Browse the repository at this point in the history
* Move search into inserter tabs

* Make inserterSearch component

* focus the search field using a useEffect

* use request animation frame

* add comment

* remove unused code

* change selector for search

* use useRefEffect instead of the requestAnimationFrame

* Only inserter on mount

* keep the imperative ref and focus once the tabs are done

* revert changes to the inserter tabs and leave the tabs contents memoized

* reset order

* remove unneeded change

* reset order

* show message if no blocks and no patterns available, do not auto focus tabs or search

* fix test

* fix firefox bug

* auto focus the inserter when open so that we can tab into it

* Remove unused searchRef

* Pin hint to bottom of block tab panel so it doesn't flash

* Remove unnecessary tab filtering

* restore no results message

* Focus first active tab

* hide the inserter tabs on the widget editor

---------

Co-authored-by: Ben Dwyer <ben@scruffian.com>
Co-authored-by: Andrei Draganescu <andrei.draganescu@automattic.com>

Co-authored-by: jeryj <jeryj@git.wordpress.org>
Co-authored-by: scruffian <scruffian@git.wordpress.org>
Co-authored-by: draganescu <andraganescu@git.wordpress.org>
Co-authored-by: getdave <get_dave@git.wordpress.org>
  • Loading branch information
5 people committed May 1, 2024
1 parent 907c8b1 commit 59ed45e
Show file tree
Hide file tree
Showing 12 changed files with 161 additions and 137 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import MobileTabNavigation from '../mobile-tab-navigation';
import { PatternCategoryPreviews } from './pattern-category-previews';
import { usePatternCategories } from './use-pattern-categories';
import CategoryTabs from '../category-tabs';
import InserterNoResults from '../no-results';

function BlockPatternsTab( {
onSelectCategory,
Expand All @@ -28,6 +29,10 @@ function BlockPatternsTab( {

const isMobile = useViewportMatch( 'medium', '<' );

if ( ! categories.length ) {
return <InserterNoResults />;
}

return (
<>
{ ! isMobile && (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import InserterPanel from './panel';
import useBlockTypesState from './hooks/use-block-types-state';
import InserterListbox from '../inserter-listbox';
import { orderBy } from '../../utils/sorting';
import InserterNoResults from './no-results';

const getBlockNamespace = ( item ) => item.name.split( '/' )[ 0 ];

Expand Down Expand Up @@ -102,6 +103,10 @@ export function BlockTypesTab( {
didRenderAllCategories ? collectionEntries : EMPTY_ARRAY
);

if ( ! items.length ) {
return <InserterNoResults />;
}

return (
<InserterListbox>
<div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { useMediaCategories } from './hooks';
import { getBlockAndPreviewFromMedia } from './utils';
import MobileTabNavigation from '../mobile-tab-navigation';
import CategoryTabs from '../category-tabs';
import InserterNoResults from '../no-results';

const ALLOWED_MEDIA_TYPES = [ 'image', 'video', 'audio' ];

Expand Down Expand Up @@ -48,6 +49,10 @@ function MediaTab( {
[ mediaCategories ]
);

if ( ! categories.length ) {
return <InserterNoResults />;
}

return (
<>
{ ! isMobile && (
Expand Down
229 changes: 120 additions & 109 deletions packages/block-editor/src/components/inserter/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,28 +11,25 @@ import {
useState,
useCallback,
useMemo,
useImperativeHandle,
useRef,
useLayoutEffect,
} from '@wordpress/element';
import { VisuallyHidden, SearchControl, Popover } from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { useSelect } from '@wordpress/data';
import { useDebouncedInput } from '@wordpress/compose';

/**
* Internal dependencies
*/
import { unlock } from '../../lock-unlock';
import Tips from './tips';
import InserterPreviewPanel from './preview-panel';
import BlockTypesTab from './block-types-tab';
import BlockPatternsTab from './block-patterns-tab';
import { PatternCategoryPreviewPanel } from './block-patterns-tab/pattern-category-preview-panel';
import { MediaTab, MediaCategoryPanel, useMediaCategories } from './media-tab';
import { MediaTab, MediaCategoryPanel } from './media-tab';
import InserterSearchResults from './search-results';
import useInsertionPoint from './hooks/use-insertion-point';
import InserterTabs from './tabs';
import { store as blockEditorStore } from '../../store';
import { useZoomOut } from '../../hooks/use-zoom-out';

const NOOP = () => {};
Expand All @@ -59,7 +56,7 @@ function InserterMenu(
const [ patternFilter, setPatternFilter ] = useState( 'all' );
const [ selectedMediaCategory, setSelectedMediaCategory ] =
useState( null );
const [ selectedTab, setSelectedTab ] = useState( null );
const [ selectedTab, setSelectedTab ] = useState( 'blocks' );

const [ destinationRootClientId, onInsertBlocks, onToggleInsertionPoint ] =
useInsertionPoint( {
Expand All @@ -69,18 +66,6 @@ function InserterMenu(
insertionIndex: __experimentalInsertionIndex,
shouldFocusBlock,
} );
const { showPatterns } = useSelect(
( select ) => {
const { hasAllowedPatterns } = unlock( select( blockEditorStore ) );
return {
showPatterns: hasAllowedPatterns( destinationRootClientId ),
};
},
[ destinationRootClientId ]
);

const mediaCategories = useMediaCategories( destinationRootClientId );
const showMedia = mediaCategories.length > 0;

const onInsert = useCallback(
( blocks, meta, shouldForceFocusBlock ) => {
Expand Down Expand Up @@ -135,29 +120,86 @@ function InserterMenu(
! delayedFilterValue &&
selectedPatternCategory;

const showMediaPanel =
selectedTab === 'media' &&
! delayedFilterValue &&
selectedMediaCategory;
const showMediaPanel = selectedTab === 'media' && selectedMediaCategory;

const blocksTab = useMemo(
() => (
const inserterSearch = useMemo( () => {
if ( selectedTab === 'media' ) {
return null;
}
return (
<>
<div className="block-editor-inserter__block-list">
<BlockTypesTab
rootClientId={ destinationRootClientId }
onInsert={ onInsert }
<SearchControl
__nextHasNoMarginBottom
className="block-editor-inserter__search"
onChange={ ( value ) => {
if ( hoveredItem ) {
setHoveredItem( null );
}
setFilterValue( value );
} }
value={ filterValue }
label={ __( 'Search for blocks and patterns' ) }
placeholder={ __( 'Search' ) }
/>
{ !! delayedFilterValue && (
<InserterSearchResults
filterValue={ delayedFilterValue }
onSelect={ onSelect }
onHover={ onHover }
showMostUsedBlocks={ showMostUsedBlocks }
onHoverPattern={ onHoverPattern }
rootClientId={ rootClientId }
clientId={ clientId }
isAppender={ isAppender }
__experimentalInsertionIndex={
__experimentalInsertionIndex
}
showBlockDirectory
shouldFocusBlock={ shouldFocusBlock }
prioritizePatterns={ selectedTab === 'patterns' }
/>
</div>
{ showInserterHelpPanel && (
<div className="block-editor-inserter__tips">
<VisuallyHidden as="h2">
{ __( 'A tip for using the block editor' ) }
</VisuallyHidden>
<Tips />
</div>
) }
</>
);
}, [
selectedTab,
hoveredItem,
setHoveredItem,
setFilterValue,
filterValue,
delayedFilterValue,
onSelect,
onHover,
onHoverPattern,
shouldFocusBlock,
clientId,
rootClientId,
__experimentalInsertionIndex,
isAppender,
] );

const blocksTab = useMemo(
() => (
<>
{ inserterSearch }
{ ! delayedFilterValue && (
<>
<div className="block-editor-inserter__block-list">
<BlockTypesTab
rootClientId={ destinationRootClientId }
onInsert={ onInsert }
onHover={ onHover }
showMostUsedBlocks={ showMostUsedBlocks }
/>
</div>
{ showInserterHelpPanel && (
<div className="block-editor-inserter__tips">
<VisuallyHidden as="h2">
{ __( 'A tip for using the block editor' ) }
</VisuallyHidden>
<Tips />
</div>
) }
</>
) }
</>
),
Expand All @@ -167,28 +209,35 @@ function InserterMenu(
onHover,
showMostUsedBlocks,
showInserterHelpPanel,
inserterSearch,
delayedFilterValue,
]
);

const patternsTab = useMemo(
() => (
<BlockPatternsTab
rootClientId={ destinationRootClientId }
onInsert={ onInsertPattern }
onSelectCategory={ onClickPatternCategory }
selectedCategory={ selectedPatternCategory }
>
{ showPatternPanel && (
<PatternCategoryPreviewPanel
<>
{ inserterSearch }
{ ! delayedFilterValue && (
<BlockPatternsTab
rootClientId={ destinationRootClientId }
onInsert={ onInsertPattern }
onHover={ onHoverPattern }
category={ selectedPatternCategory }
patternFilter={ patternFilter }
showTitlesAsTooltip
/>
onSelectCategory={ onClickPatternCategory }
selectedCategory={ selectedPatternCategory }
>
{ showPatternPanel && (
<PatternCategoryPreviewPanel
rootClientId={ destinationRootClientId }
onInsert={ onInsertPattern }
onHover={ onHoverPattern }
category={ selectedPatternCategory }
patternFilter={ patternFilter }
showTitlesAsTooltip
/>
) }
</BlockPatternsTab>
) }
</BlockPatternsTab>
</>
),
[
destinationRootClientId,
Expand All @@ -198,6 +247,8 @@ function InserterMenu(
patternFilter,
selectedPatternCategory,
showPatternPanel,
inserterSearch,
delayedFilterValue,
]
);

Expand Down Expand Up @@ -236,15 +287,6 @@ function InserterMenu(
[ blocksTab, mediaTab, patternsTab ]
);

const searchRef = useRef();
useImperativeHandle( ref, () => ( {
focusSearch: () => {
searchRef.current.focus();
},
} ) );

const showAsTabs = ! delayedFilterValue && ( showPatterns || showMedia );

// When the pattern panel is showing, we want to use zoom out mode
useZoomOut( showPatternPanel );

Expand All @@ -256,62 +298,31 @@ function InserterMenu(
setSelectedTab( value );
};

// Focus first active tab, if any
const tabsRef = useRef();
useLayoutEffect( () => {
if ( tabsRef.current ) {
window.requestAnimationFrame( () => {
tabsRef.current
.querySelector( '[role="tab"][aria-selected="true"]' )
?.focus();
} );
}
}, [] );

return (
<div
className={ classnames( 'block-editor-inserter__menu', {
'show-panel': showPatternPanel || showMediaPanel,
} ) }
ref={ ref }
>
<div
className={ classnames( 'block-editor-inserter__main-area', {
'show-as-tabs': showAsTabs,
} ) }
>
<SearchControl
__nextHasNoMarginBottom
className="block-editor-inserter__search"
onChange={ ( value ) => {
if ( hoveredItem ) {
setHoveredItem( null );
}
setFilterValue( value );
} }
value={ filterValue }
label={ __( 'Search for blocks and patterns' ) }
placeholder={ __( 'Search' ) }
ref={ searchRef }
<div className="block-editor-inserter__main-area">
<InserterTabs
ref={ tabsRef }
onSelect={ handleSetSelectedTab }
tabsContents={ inserterTabsContents }
/>
{ !! delayedFilterValue && (
<div className="block-editor-inserter__no-tab-container">
<InserterSearchResults
filterValue={ delayedFilterValue }
onSelect={ onSelect }
onHover={ onHover }
onHoverPattern={ onHoverPattern }
rootClientId={ rootClientId }
clientId={ clientId }
isAppender={ isAppender }
__experimentalInsertionIndex={
__experimentalInsertionIndex
}
showBlockDirectory
shouldFocusBlock={ shouldFocusBlock }
/>
</div>
) }
{ showAsTabs && (
<InserterTabs
showPatterns={ showPatterns }
showMedia={ showMedia }
onSelect={ handleSetSelectedTab }
tabsContents={ inserterTabsContents }
/>
) }
{ ! delayedFilterValue && ! showAsTabs && (
<div className="block-editor-inserter__no-tab-container">
{ blocksTab }
</div>
) }
</div>
{ showInserterHelpPanel && hoveredItem && (
<Popover
Expand Down
5 changes: 5 additions & 0 deletions packages/block-editor/src/components/inserter/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,11 @@ $block-inserter-tabs-height: 44px;
flex-direction: column;
overflow-y: auto;
}

// The first tab panel needs space-between to prevent a flash of the "hint" from appearing at the top then moving down.
.block-editor-inserter__tablist + .block-editor-inserter__tabpanel {
justify-content: space-between;
}
}

.block-editor-inserter__no-tab-container {
Expand Down
Loading

1 comment on commit 59ed45e

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flaky tests detected in 59ed45e.
Some tests passed with failed attempts. The failures may not be related to this commit but are still reported for visibility. See the documentation for more information.

🔍 Workflow run URL: https://github.com/WordPress/gutenberg/actions/runs/8912074447
📝 Reported issues:

Please sign in to comment.