Skip to content

Commit

Permalink
Fix navigation editor missing appender not showing appender when no b…
Browse files Browse the repository at this point in the history
…locks selected (#34678)

* Support custom appender in the nav block

* Implement the toggle style appender in the nav editor

* Update rendering logic for appender

* Fix comment

* Add e2e test
  • Loading branch information
talldan authored Sep 13, 2021
1 parent 3531c71 commit f74bbde
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
/**
* External dependencies
*/
import classnames from 'classnames';

/**
* Internal dependencies
*/
Expand All @@ -9,9 +14,13 @@ export const ButtonBlockAppender = ( {
showSeparator,
isFloating,
onAddBlock,
isToggle,
} ) => {
return (
<BaseButtonBlockAppender
className={ classnames( {
'block-list-appender__toggle': isToggle,
} ) }
rootClientId={ clientId }
showSeparator={ showSeparator }
isFloating={ isFloating }
Expand Down
22 changes: 15 additions & 7 deletions packages/block-library/src/navigation/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import {
Platform,
} from '@wordpress/element';
import {
InnerBlocks,
__experimentalUseInnerBlocksProps as useInnerBlocksProps,
InspectorControls,
JustifyToolbar,
Expand Down Expand Up @@ -101,10 +100,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
Expand Down Expand Up @@ -146,19 +149,24 @@ function Navigation( {

const placeholder = useMemo( () => <PlaceholderPreview />, [] );

// 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',
},
{
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.
Expand Down
16 changes: 16 additions & 0 deletions packages/e2e-tests/specs/experiments/navigation-editor.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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 ) } ),
Expand Down
8 changes: 8 additions & 0 deletions packages/edit-navigation/src/components/editor/style.scss
Original file line number Diff line number Diff line change
Expand Up @@ -165,4 +165,12 @@
padding: 0;
}
}

// 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;
transform: unset;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/**
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';
import { addFilter } from '@wordpress/hooks';
import { createHigherOrderComponent } from '@wordpress/compose';
import {
InnerBlocks,
store as blockEditorStore,
} from '@wordpress/block-editor';

function CustomAppender() {
return <InnerBlocks.ButtonBlockAppender isToggle />;
}

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 <BlockEdit { ...props } customAppender={ customAppender } />;
}

const addNavigationEditorCustomAppender = createHigherOrderComponent(
( BlockEdit ) => ( props ) => {
if ( props.name !== 'core/navigation' ) {
return <BlockEdit { ...props } />;
}

// Use a separate component so that `useSelect` only run on the navigation block.
return <EnhancedNavigationBlock blockEdit={ BlockEdit } { ...props } />;
},
'withNavigationEditorCustomAppender'
);

export default () =>
addFilter(
'editor.BlockEdit',
'core/edit-navigation/with-navigation-editor-custom-appender',
addNavigationEditorCustomAppender
);
Original file line number Diff line number Diff line change
@@ -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(
Expand Down
2 changes: 2 additions & 0 deletions packages/edit-navigation/src/filters/index.js
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -10,6 +11,7 @@ import removeSettingsUnsupportedFeatures from './remove-settings-unsupported-fea
export const addFilters = (
shouldAddDisableInsertingNonNavigationBlocksFilter
) => {
addNavigationEditorCustomAppender();
addNavigationEditorPlaceholder();
addMenuNameEditor();
if ( shouldAddDisableInsertingNonNavigationBlocksFilter ) {
Expand Down

0 comments on commit f74bbde

Please sign in to comment.