Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Try: Customize navigation block behavior using block context #35351

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/block-library/src/navigation/block.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
"__experimentalTextDecoration": true
}
},
"usesContext": [ "navigation" ],
"viewScript": "file:./view.min.js",
"editorStyle": "wp-block-navigation-editor",
"style": "wp-block-navigation"
Expand Down
71 changes: 39 additions & 32 deletions packages/block-library/src/navigation/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* External dependencies
*/
import classnames from 'classnames';
import { defaults } from 'lodash';

/**
* WordPress dependencies
Expand Down Expand Up @@ -38,17 +39,25 @@ import NavigationPlaceholder from './placeholder';
import PlaceholderPreview from './placeholder-preview';
import ResponsiveWrapper from './responsive-wrapper';

const ALLOWED_BLOCKS = [
'core/navigation-link',
'core/search',
'core/social-links',
'core/page-list',
'core/spacer',
'core/home-link',
'core/site-title',
'core/site-logo',
'core/navigation-submenu',
];
const CONTEXT_DEFAULTS = {
allowedBlocks: [
'core/navigation-link',
'core/search',
'core/social-links',
'core/page-list',
'core/spacer',
'core/home-link',
'core/site-title',
'core/site-logo',
'core/navigation-submenu',
],
hasSubmenuIndicatorSetting: true,
hasItemJustificationControls: true,
hasColorSettings: true,
placeholder: NavigationPlaceholder,
createAppender: ( wouldNavBlockShowAppender ) =>
wouldNavBlockShowAppender ? undefined : false,
};

const DEFAULT_BLOCK = [ 'core/navigation-link' ];

Expand Down Expand Up @@ -96,6 +105,7 @@ function Navigation( {
selectedBlockHasDescendants,
attributes,
setAttributes,
context: { navigation },
clientId,
hasExistingNavItems,
isImmediateParentOfSelectedBlock,
Expand All @@ -110,14 +120,6 @@ 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 All @@ -126,6 +128,10 @@ function Navigation( {
false
);

// The context is used by the navigation editor to override specific
// navigation block settings.
const navContext = defaults( navigation, CONTEXT_DEFAULTS );

const { selectBlock } = useDispatch( blockEditorStore );

const navRef = useRef();
Expand Down Expand Up @@ -162,22 +168,22 @@ function Navigation( {
// 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 =
const wouldNavBlockShowAppender =
isSelected ||
( isImmediateParentOfSelectedBlock && ! selectedBlockHasDescendants )
? undefined
: false;
( isImmediateParentOfSelectedBlock && ! selectedBlockHasDescendants );

const innerBlocksProps = useInnerBlocksProps(
{
className: 'wp-block-navigation__container',
},
{
allowedBlocks: ALLOWED_BLOCKS,
allowedBlocks: navContext.allowedBlocks,
__experimentalDefaultBlock: DEFAULT_BLOCK,
__experimentalDirectInsert: DIRECT_INSERT,
orientation: attributes.orientation,
renderAppender: CustomAppender || appender,
renderAppender: navContext.createAppender(
wouldNavBlockShowAppender
),

// Ensure block toolbar is not too far removed from item
// being edited when in vertical mode.
Expand All @@ -189,7 +195,10 @@ function Navigation( {
// inherit templateLock={ 'all' }.
templateLock: false,
__experimentalLayout: LAYOUT,
placeholder: ! CustomPlaceholder ? placeholder : undefined,
placeholder:
navContext.placeholder === CONTEXT_DEFAULTS.placeholder
? placeholder
: undefined,
}
);

Expand Down Expand Up @@ -226,9 +235,7 @@ function Navigation( {
} );

if ( isPlaceholderShown ) {
const PlaceholderComponent = CustomPlaceholder
? CustomPlaceholder
: NavigationPlaceholder;
const PlaceholderComponent = navContext.placeholder;

return (
<div { ...blockProps }>
Expand All @@ -253,7 +260,7 @@ function Navigation( {
return (
<>
<BlockControls>
{ hasItemJustificationControls && (
{ navContext.hasItemJustificationControls && (
<JustifyToolbar
value={ attributes.itemsJustification }
allowedControls={ justifyAllowedControls }
Expand All @@ -270,7 +277,7 @@ function Navigation( {
</BlockControls>
{ navigatorModal }
<InspectorControls>
{ hasSubmenuIndicatorSetting && (
{ navContext.hasSubmenuIndicatorSetting && (
<PanelBody title={ __( 'Display settings' ) }>
<ToggleControl
checked={ attributes.isResponsive }
Expand Down Expand Up @@ -303,7 +310,7 @@ function Navigation( {
) }
</PanelBody>
) }
{ hasColorSettings && (
{ navContext.hasColorSettings && (
<PanelColorSettings
title={ __( 'Color' ) }
initialOpen={ false }
Expand Down
174 changes: 106 additions & 68 deletions packages/edit-navigation/src/components/layout/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,13 @@
* WordPress dependencies
*/
import {
BlockContextProvider,
BlockEditorKeyboardShortcuts,
BlockEditorProvider,
BlockTools,
InnerBlocks,
__unstableUseBlockSelectionClearer as useBlockSelectionClearer,
store as blockEditorStore,
} from '@wordpress/block-editor';
import { useEntityBlockEditor } from '@wordpress/core-data';
import { Popover, SlotFillProvider, Spinner } from '@wordpress/components';
Expand Down Expand Up @@ -41,6 +44,7 @@ import {
NAVIGATION_POST_KIND,
NAVIGATION_POST_POST_TYPE,
} from '../../constants';
import BlockPlaceholder from '../block-placeholder';

const interfaceLabels = {
/* translators: accessibility text for the navigation screen top bar landmark region. */
Expand All @@ -52,6 +56,10 @@ const interfaceLabels = {
secondarySidebar: __( 'Block library' ),
};

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

export default function Layout( { blockEditorSettings } ) {
const contentAreaRef = useBlockSelectionClearer();
const [ isMenuNameControlFocused, setIsMenuNameControlFocused ] = useState(
Expand Down Expand Up @@ -80,16 +88,40 @@ export default function Layout( { blockEditorSettings } ) {
}
);

const { hasSidebarEnabled, isInserterOpened } = useSelect(
const { hasSidebarEnabled, isInserterOpened, noBlockSelected } = useSelect(
( select ) => ( {
hasSidebarEnabled: !! select(
interfaceStore
).getActiveComplementaryArea( 'core/edit-navigation' ),
isInserterOpened: select( editNavigationStore ).isInserterOpened(),
noBlockSelected: ! select(
blockEditorStore
).getSelectedBlockClientId(),
} ),
[]
);

const blockContext = useMemo( () => {
const context = {
hasSubmenuIndicatorSetting: false,
hasItemJustificationControls: false,
hasColorSettings: false,
placeholder: BlockPlaceholder,
createAppender: ( wouldNavBlockShowAppender ) =>
wouldNavBlockShowAppender || noBlockSelected
? CustomAppender
: false,
};
if ( ! blockEditorSettings.blockNavMenus ) {
context.allowedBlocks = [
'core/navigation',
'core/navigation-link',
'core/navigation-submenu',
];
}
return { navigation: context };
}, [ blockEditorSettings.blockNavMenus, noBlockSelected ] );

useEffect( () => {
if ( ! selectedMenuId && menus?.length ) {
selectMenu( menus[ 0 ].id );
Expand Down Expand Up @@ -127,77 +159,83 @@ export default function Layout( { blockEditorSettings } ) {
} }
useSubRegistry={ false }
>
<IsMenuNameControlFocusedContext.Provider
value={ useMemo(
() => [
isMenuNameControlFocused,
setIsMenuNameControlFocused,
],
[ isMenuNameControlFocused ]
) }
>
<InterfaceSkeleton
className="edit-navigation-layout"
labels={ interfaceLabels }
header={
<Header
isMenuSelected={ isMenuSelected }
isPending={ ! hasLoadedMenus }
menus={ menus }
navigationPost={ navigationPost }
/>
}
content={
<>
<Notices />
{ ! hasFinishedInitialLoad && (
<Spinner />
) }

{ ! isMenuSelected &&
hasFinishedInitialLoad && (
<UnselectedMenuState
onSelectMenu={ selectMenu }
onCreate={ selectMenu }
menus={ menus }
/>
<BlockContextProvider value={ blockContext }>
<IsMenuNameControlFocusedContext.Provider
value={ useMemo(
() => [
isMenuNameControlFocused,
setIsMenuNameControlFocused,
],
[ isMenuNameControlFocused ]
) }
>
<InterfaceSkeleton
className="edit-navigation-layout"
labels={ interfaceLabels }
header={
<Header
isMenuSelected={ isMenuSelected }
isPending={ ! hasLoadedMenus }
menus={ menus }
navigationPost={ navigationPost }
/>
}
content={
<>
<Notices />
{ ! hasFinishedInitialLoad && (
<Spinner />
) }
{ isBlockEditorReady && (
<div
className="edit-navigation-layout__content-area"
ref={ contentAreaRef }
>
<BlockTools>
<Editor
isPending={
! hasLoadedMenus

{ ! isMenuSelected &&
hasFinishedInitialLoad && (
<UnselectedMenuState
onSelectMenu={
selectMenu
}
onCreate={ selectMenu }
menus={ menus }
/>
</BlockTools>
</div>
) }
</>
}
sidebar={
hasSidebarEnabled && (
<ComplementaryArea.Slot scope="core/edit-navigation" />
)
}
secondarySidebar={
isInserterOpened && <InserterSidebar />
}
/>
{ isMenuSelected && (
<Sidebar
menus={ menus }
menuId={ selectedMenuId }
onSelectMenu={ selectMenu }
onDeleteMenu={ deleteMenu }
isMenuBeingDeleted={ isMenuBeingDeleted }
) }
{ isBlockEditorReady && (
<div
className="edit-navigation-layout__content-area"
ref={ contentAreaRef }
>
<BlockTools>
<Editor
isPending={
! hasLoadedMenus
}
/>
</BlockTools>
</div>
) }
</>
}
sidebar={
hasSidebarEnabled && (
<ComplementaryArea.Slot scope="core/edit-navigation" />
)
}
secondarySidebar={
isInserterOpened && <InserterSidebar />
}
/>
) }
</IsMenuNameControlFocusedContext.Provider>
<UnsavedChangesWarning />
{ isMenuSelected && (
<Sidebar
menus={ menus }
menuId={ selectedMenuId }
onSelectMenu={ selectMenu }
onDeleteMenu={ deleteMenu }
isMenuBeingDeleted={
isMenuBeingDeleted
}
/>
) }
</IsMenuNameControlFocusedContext.Provider>
<UnsavedChangesWarning />
</BlockContextProvider>
</BlockEditorProvider>
<Popover.Slot />
</SlotFillProvider>
Expand Down
Loading