From a4e38e756e8c4390a8e4aac74b2fd25faca03c41 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Thu, 9 Sep 2021 12:38:18 +0800 Subject: [PATCH 1/5] Support custom appender in the nav block --- packages/block-library/src/navigation/edit.js | 22 +++++++++++++------ 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/packages/block-library/src/navigation/edit.js b/packages/block-library/src/navigation/edit.js index bdab02b4b7c80a..129bfc9ee5be30 100644 --- a/packages/block-library/src/navigation/edit.js +++ b/packages/block-library/src/navigation/edit.js @@ -14,7 +14,6 @@ import { Platform, } from '@wordpress/element'; import { - InnerBlocks, __experimentalUseInnerBlocksProps as useInnerBlocksProps, InspectorControls, JustifyToolbar, @@ -100,10 +99,14 @@ function Navigation( { setOverlayBackgroundColor, overlayTextColor, setOverlayTextColor, + + // These props are used by the navigation editor to override specific + // navigation block settings. hasSubmenuIndicatorSetting = true, hasItemJustificationControls = true, hasColorSettings = true, customPlaceholder: CustomPlaceholder = null, + customAppender: CustomAppender = null, } ) { const [ isPlaceholderShown, setIsPlaceholderShown ] = useState( ! hasExistingNavItems @@ -145,6 +148,15 @@ function Navigation( { const placeholder = useMemo( () => , [] ); + // When the block is selected itself or has a top level item selected that + // doesn't itself have children, show the standard appender. Else show no + // appender. + const appender = + isSelected || + ( isImmediateParentOfSelectedBlock && ! selectedBlockHasDescendants ) + ? undefined + : false; + const innerBlocksProps = useInnerBlocksProps( { className: 'wp-block-navigation__container', @@ -152,12 +164,8 @@ function Navigation( { { allowedBlocks: ALLOWED_BLOCKS, orientation: attributes.orientation, - renderAppender: - ( isImmediateParentOfSelectedBlock && - ! selectedBlockHasDescendants ) || - isSelected - ? InnerBlocks.DefaultAppender - : false, + renderAppender: CustomAppender || appender, + // Ensure block toolbar is not too far removed from item // being edited when in vertical mode. // see: https://github.com/WordPress/gutenberg/pull/34615. From 68e331afc7f3578cd6ae2f628be3fec42b5c1bd9 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Thu, 9 Sep 2021 13:10:22 +0800 Subject: [PATCH 2/5] Implement the toggle style appender in the nav editor --- .../inner-blocks/button-block-appender.js | 9 ++++++ .../src/components/editor/style.scss | 8 ++++++ .../add-navigation-editor-custom-appender.js | 28 +++++++++++++++++++ .../add-navigation-editor-placeholder.js | 5 ++-- packages/edit-navigation/src/filters/index.js | 2 ++ 5 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 packages/edit-navigation/src/filters/add-navigation-editor-custom-appender.js diff --git a/packages/block-editor/src/components/inner-blocks/button-block-appender.js b/packages/block-editor/src/components/inner-blocks/button-block-appender.js index 88bd12bd46b771..5319b5d4d3c368 100644 --- a/packages/block-editor/src/components/inner-blocks/button-block-appender.js +++ b/packages/block-editor/src/components/inner-blocks/button-block-appender.js @@ -1,3 +1,8 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + /** * Internal dependencies */ @@ -9,9 +14,13 @@ export const ButtonBlockAppender = ( { showSeparator, isFloating, onAddBlock, + isToggle, } ) => { return ( .block-list-appender .block-list-appender__toggle { + opacity: unset; + transform: unset; + } + } } diff --git a/packages/edit-navigation/src/filters/add-navigation-editor-custom-appender.js b/packages/edit-navigation/src/filters/add-navigation-editor-custom-appender.js new file mode 100644 index 00000000000000..d35f829c4ad24d --- /dev/null +++ b/packages/edit-navigation/src/filters/add-navigation-editor-custom-appender.js @@ -0,0 +1,28 @@ +/** + * WordPress dependencies + */ +import { addFilter } from '@wordpress/hooks'; +import { createHigherOrderComponent } from '@wordpress/compose'; +import { InnerBlocks } from '@wordpress/block-editor'; + +function CustomAppender() { + return ; +} + +const addNavigationEditorCustomAppender = createHigherOrderComponent( + ( BlockEdit ) => ( props ) => { + if ( props.name !== 'core/navigation' ) { + return ; + } + + return ; + }, + 'withNavigationEditorCustomAppender' +); + +export default () => + addFilter( + 'editor.BlockEdit', + 'core/edit-navigation/with-navigation-editor-custom-appender', + addNavigationEditorCustomAppender + ); diff --git a/packages/edit-navigation/src/filters/add-navigation-editor-placeholder.js b/packages/edit-navigation/src/filters/add-navigation-editor-placeholder.js index 263658d0ffc646..94b62fea180572 100644 --- a/packages/edit-navigation/src/filters/add-navigation-editor-placeholder.js +++ b/packages/edit-navigation/src/filters/add-navigation-editor-placeholder.js @@ -1,11 +1,12 @@ /** * WordPress dependencies */ +import { addFilter } from '@wordpress/hooks'; +import { createHigherOrderComponent } from '@wordpress/compose'; + /** * Internal dependencies */ -import { addFilter } from '@wordpress/hooks'; -import { createHigherOrderComponent } from '@wordpress/compose'; import BlockPlaceholder from '../components/block-placeholder'; const addNavigationEditorPlaceholder = createHigherOrderComponent( diff --git a/packages/edit-navigation/src/filters/index.js b/packages/edit-navigation/src/filters/index.js index 08ab87f0fe4b5d..17074eb87c6603 100644 --- a/packages/edit-navigation/src/filters/index.js +++ b/packages/edit-navigation/src/filters/index.js @@ -1,6 +1,7 @@ /** * Internal dependencies */ +import addNavigationEditorCustomAppender from './add-navigation-editor-custom-appender'; import addNavigationEditorPlaceholder from './add-navigation-editor-placeholder'; import addMenuNameEditor from './add-menu-name-editor'; import disableInsertingNonNavigationBlocks from './disable-inserting-non-navigation-blocks'; @@ -10,6 +11,7 @@ import removeSettingsUnsupportedFeatures from './remove-settings-unsupported-fea export const addFilters = ( shouldAddDisableInsertingNonNavigationBlocksFilter ) => { + addNavigationEditorCustomAppender(); addNavigationEditorPlaceholder(); addMenuNameEditor(); if ( shouldAddDisableInsertingNonNavigationBlocksFilter ) { From 720fca4324b9947893b195ca092e063544647da9 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Thu, 9 Sep 2021 13:24:12 +0800 Subject: [PATCH 3/5] Update rendering logic for appender --- .../add-navigation-editor-custom-appender.js | 52 ++++++++++++++++++- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/packages/edit-navigation/src/filters/add-navigation-editor-custom-appender.js b/packages/edit-navigation/src/filters/add-navigation-editor-custom-appender.js index d35f829c4ad24d..6a3b5f64e94dce 100644 --- a/packages/edit-navigation/src/filters/add-navigation-editor-custom-appender.js +++ b/packages/edit-navigation/src/filters/add-navigation-editor-custom-appender.js @@ -1,21 +1,69 @@ /** * WordPress dependencies */ +import { useSelect } from '@wordpress/data'; import { addFilter } from '@wordpress/hooks'; import { createHigherOrderComponent } from '@wordpress/compose'; -import { InnerBlocks } from '@wordpress/block-editor'; +import { + InnerBlocks, + store as blockEditorStore, +} from '@wordpress/block-editor'; function CustomAppender() { return ; } +function EnhancedNavigationBlock( { blockEdit: BlockEdit, ...props } ) { + const clientId = props.clientId; + const { + noBlockSelected, + isSelected, + isImmediateParentOfSelectedBlock, + selectedBlockHasDescendants, + } = useSelect( + ( select ) => { + const { + getClientIdsOfDescendants, + hasSelectedInnerBlock, + getSelectedBlockClientId, + } = select( blockEditorStore ); + const _isImmediateParentOfSelectedBlock = hasSelectedInnerBlock( + clientId, + false + ); + const selectedBlockId = getSelectedBlockClientId(); + const _selectedBlockHasDescendants = !! getClientIdsOfDescendants( [ + selectedBlockId, + ] )?.length; + + return { + isSelected: selectedBlockId === clientId, + noBlockSelected: ! selectedBlockId, + isImmediateParentOfSelectedBlock: _isImmediateParentOfSelectedBlock, + selectedBlockHasDescendants: _selectedBlockHasDescendants, + }; + }, + [ clientId ] + ); + + const customAppender = + noBlockSelected || + isSelected || + ( isImmediateParentOfSelectedBlock && ! selectedBlockHasDescendants ) + ? CustomAppender + : false; + + return ; +} + const addNavigationEditorCustomAppender = createHigherOrderComponent( ( BlockEdit ) => ( props ) => { if ( props.name !== 'core/navigation' ) { return ; } - return ; + // Use a separate component so that `useSelect` only run on the navigation block. + return ; }, 'withNavigationEditorCustomAppender' ); From fbd5b430094720fc64ca4ac1331d6e73715f9c58 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Thu, 9 Sep 2021 14:25:29 +0800 Subject: [PATCH 4/5] Fix comment --- packages/edit-navigation/src/components/editor/style.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-navigation/src/components/editor/style.scss b/packages/edit-navigation/src/components/editor/style.scss index 6d2b2bbd1f587f..d48af467b1ab39 100644 --- a/packages/edit-navigation/src/components/editor/style.scss +++ b/packages/edit-navigation/src/components/editor/style.scss @@ -165,7 +165,7 @@ } } - // Override behavior that hides the navigation block's appender when it's selected. + // Override behavior that hides the navigation block's appender when it's deselected. .block-editor-block-list__block:not(.is-selected):not(.has-child-selected):not(.block-editor-block-list__layout) { .block-editor-block-list__layout > .block-list-appender .block-list-appender__toggle { opacity: unset; From ad9bf1bd61766c794daa721c781d1ee129ba19f7 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Fri, 10 Sep 2021 16:21:24 +0800 Subject: [PATCH 5/5] Add e2e test --- .../specs/experiments/navigation-editor.test.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/e2e-tests/specs/experiments/navigation-editor.test.js b/packages/e2e-tests/specs/experiments/navigation-editor.test.js index 972ba27eb834b3..16d343c6f91edb 100644 --- a/packages/e2e-tests/specs/experiments/navigation-editor.test.js +++ b/packages/e2e-tests/specs/experiments/navigation-editor.test.js @@ -315,6 +315,22 @@ describe( 'Navigation editor', () => { expect( await getSerializedBlocks() ).toMatchSnapshot(); } ); + it( 'shows the trailing block appender within the navigation block when no blocks are selected', async () => { + await setUpResponseMocking( [ + ...getMenuMocks( { GET: assignMockMenuIds( menusFixture ) } ), + ...getMenuItemMocks( { GET: menuItemsFixture } ), + ] ); + await visitNavigationEditor(); + + const selectedBlocks = await page.$$( '.wp-block.is-selected' ); + expect( selectedBlocks.length ).toBe( 0 ); + + const blockListAppender = await page.$( + '.block-list-appender button[aria-label="Add block"]' + ); + expect( blockListAppender ).toBeTruthy(); + } ); + it( 'shows a submenu when a link is selected and hides it when clicking the editor to deselect it', async () => { await setUpResponseMocking( [ ...getMenuMocks( { GET: assignMockMenuIds( menusFixture ) } ),