Skip to content

Commit

Permalink
First stab at editable menu items in navigator
Browse files Browse the repository at this point in the history
Use Slot/Fill instead of hardcoded components

Disable slots/fills in global editor block navigator

Grab clientId from context instead of requiring a prop

Improve readability of block-navigation/list.js

Use context to determine whether or not given BlockNavigation may be customized with slots

Restore default value for selectBlock in navigation-structure-panel.js

Remove obsolete onChange passed to NavigationStructurePanel

Use constant value for BlockNavigationContext

Use memo() in BlockStyles

Remove performance changes from BlockStyles

Generalize BlockNavigationListItem and remove the BlockNavigationListItemFill for now

Rename useBlockNavigationSlots to withBlockNavigationSlots

Restore RichText in the navigator

Sort out BlockNavigationListItem and BlockNavigationListItemWrapper

Rename BlockNavigationListItemWrapper to BlockNavigationBranch
  • Loading branch information
adamziel committed May 5, 2020
1 parent 9db5982 commit 32543c0
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 50 deletions.
58 changes: 58 additions & 0 deletions packages/block-editor/src/components/block-navigation/list-item.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/**
* External dependencies
*/
import classnames from 'classnames';

/**
* WordPress dependencies
*/
import { Button, VisuallyHidden } from '@wordpress/components';
import {
__experimentalGetBlockLabel as getBlockLabel,
getBlockType,
} from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import BlockIcon from '../block-icon';

export default function BlockNavigationListItem( {
block,
onClick,
isSelected,
wrapperComponent: WrapperComponent,
children,
} ) {
const blockType = getBlockType( block.name );

return (
<div className="block-editor-block-navigation__item">
<WrapperComponent
className={ classnames(
'block-editor-block-navigation__item-button',
{
'is-selected': isSelected,
}
) }
onClick={ onClick }
>
<BlockIcon icon={ blockType.icon } showColors />
{ children
? children
: getBlockLabel( blockType, block.attributes ) }
{ isSelected && (
<VisuallyHidden as="span">
{ __( '(selected block)' ) }
</VisuallyHidden>
) }
</WrapperComponent>
</div>
);
}

BlockNavigationListItem.defaultProps = {
onClick: () => {},
wrapperComponent: ( props ) => <Button { ...props } />,
};
91 changes: 61 additions & 30 deletions packages/block-editor/src/components/block-navigation/list.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,28 @@
* External dependencies
*/
import { isNil, map, omitBy } from 'lodash';
import classnames from 'classnames';

/**
* WordPress dependencies
*/
import { Button, VisuallyHidden } from '@wordpress/components';
import { Slot, Fill } from '@wordpress/components';
import {
__experimentalGetBlockLabel as getBlockLabel,
getBlockType,
} from '@wordpress/blocks';
import { __ } from '@wordpress/i18n';
Children,
cloneElement,
useContext,
createContext,
} from '@wordpress/element';

/**
* Internal dependencies
*/
import BlockIcon from '../block-icon';
import BlockNavigationListItem from './list-item';
import ButtonBlockAppender from '../button-block-appender';
import { BlockListBlockContext } from '../block-list/block';

export const BlockNavigationContext = createContext( {
withBlockNavigationSlots: true,
} );

export default function BlockNavigationList( {
blocks,
Expand All @@ -30,6 +35,7 @@ export default function BlockNavigationList( {
showNestedBlocks,
parentBlockClientId,
} ) {
const { withBlockNavigationSlots } = useContext( BlockNavigationContext );
const shouldShowAppender = showAppender && !! parentBlockClientId;

return (
Expand All @@ -40,30 +46,15 @@ export default function BlockNavigationList( {
/* eslint-disable jsx-a11y/no-redundant-roles */
<ul className="block-editor-block-navigation__list" role="list">
{ map( omitBy( blocks, isNil ), ( block ) => {
const blockType = getBlockType( block.name );
const isSelected = block.clientId === selectedBlockClientId;

return (
<li key={ block.clientId }>
<div className="block-editor-block-navigation__item">
<Button
className={ classnames(
'block-editor-block-navigation__item-button',
{
'is-selected': isSelected,
}
) }
onClick={ () => selectBlock( block.clientId ) }
>
<BlockIcon icon={ blockType.icon } showColors />
{ getBlockLabel( blockType, block.attributes ) }
{ isSelected && (
<VisuallyHidden as="span">
{ __( '(selected block)' ) }
</VisuallyHidden>
) }
</Button>
</div>
<BlockNavigationBranch
withSlot={ withBlockNavigationSlots }
block={ block }
key={ block.clientId }
isSelected={ isSelected }
onClick={ () => selectBlock( block.clientId ) }
>
{ showNestedBlocks &&
!! block.innerBlocks &&
!! block.innerBlocks.length && (
Expand All @@ -78,7 +69,7 @@ export default function BlockNavigationList( {
showNestedBlocks
/>
) }
</li>
</BlockNavigationBranch>
);
} ) }
{ shouldShowAppender && (
Expand All @@ -95,3 +86,43 @@ export default function BlockNavigationList( {
/* eslint-enable jsx-a11y/no-redundant-roles */
);
}

BlockNavigationList.defaultProps = {
selectBlock: () => {},
};

const BlockNavigationBranch = ( { withSlot, children, ...props } ) => {
if ( ! withSlot ) {
return <BlockNavigationListItem { ...props } />;
}

return (
<li>
<BlockNavigationListItemSlot blockId={ props.block.clientId }>
{ ( fills ) => {
if ( ! fills.length ) {
return <BlockNavigationListItem { ...props } />;
}

return Children.map( fills, ( fill ) =>
cloneElement( fill, {
...props,
...fill.props,
} )
);
} }
</BlockNavigationListItemSlot>
{ children }
</li>
);
};

const listItemSlotName = ( blockId ) => `BlockNavigationList-item-${ blockId }`;

export const BlockNavigationListItemSlot = ( { blockId, ...props } ) => (
<Slot { ...props } name={ listItemSlotName( blockId ) } />
);
export const BlockNavigationListItemFill = ( props ) => {
const { clientId } = useContext( BlockListBlockContext );
return <Fill { ...props } name={ listItemSlotName( clientId ) } />;
};
7 changes: 6 additions & 1 deletion packages/block-editor/src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@ export { default as BlockEdit, useBlockEditContext } from './block-edit';
export { default as BlockFormatControls } from './block-format-controls';
export { default as BlockIcon } from './block-icon';
export { default as BlockNavigationDropdown } from './block-navigation/dropdown';
export { default as __experimentalBlockNavigationList } from './block-navigation/list';
export {
default as __experimentalBlockNavigationList,
BlockNavigationContext as __experimentalBlockNavigationContext,
BlockNavigationListItemFill as __experimentalBlockNavigationListItemFill,
} from './block-navigation/list';
export { default as __experimentalBlockNavigationListItem } from './block-navigation/list-item';
export { default as __experimentalBlockVariationPicker } from './block-variation-picker';
export { default as BlockVerticalAlignmentToolbar } from './block-vertical-alignment-toolbar';
export { default as ButtonBlockerAppender } from './button-block-appender';
Expand Down
57 changes: 39 additions & 18 deletions packages/block-library/src/navigation-link/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,17 @@ import {
RichText,
__experimentalLinkControl as LinkControl,
__experimentalBlock as Block,
__experimentalBlockNavigationListItemFill as BlockNavigationListItemFill,
__experimentalBlockNavigationListItem as BlockNavigationListItem,
} from '@wordpress/block-editor';
import { isURL, prependHTTP } from '@wordpress/url';
import { Fragment, useState, useEffect, useRef } from '@wordpress/element';
import {
Fragment,
useState,
useEffect,
useRef,
cloneElement,
} from '@wordpress/element';
import { placeCaretAtHorizontalEdge } from '@wordpress/dom';
import { link as linkIcon } from '@wordpress/icons';

Expand All @@ -40,6 +48,8 @@ import { link as linkIcon } from '@wordpress/icons';
*/
import { ToolbarSubmenuIcon, ItemSubmenuIcon } from './icons';

const noop = () => {};

function NavigationLinkEdit( {
attributes,
hasDescendants,
Expand Down Expand Up @@ -129,6 +139,25 @@ function NavigationLinkEdit( {
};
}

const editField = (
<RichText
className="wp-block-navigation-link__label"
value={ label }
onChange={ ( labelValue ) =>
setAttributes( { label: labelValue } )
}
placeholder={ itemLabelPlaceholder }
keepPlaceholderOnFocus
withoutInteractiveFormatting
allowedFormats={ [
'core/bold',
'core/italic',
'core/image',
'core/strikethrough',
] }
/>
);

return (
<Fragment>
<BlockControls>
Expand Down Expand Up @@ -193,6 +222,14 @@ function NavigationLinkEdit( {
/>
</PanelBody>
</InspectorControls>
<BlockNavigationListItemFill>
<BlockNavigationListItem
wrapperComponent="div"
onClick={ noop }
>
{ editField }
</BlockNavigationListItem>
</BlockNavigationListItemFill>
<Block.li
className={ classnames( {
'is-editing': isSelected || isParentOfSelectedBlock,
Expand All @@ -210,23 +247,7 @@ function NavigationLinkEdit( {
} }
>
<div className="wp-block-navigation-link__content">
<RichText
ref={ ref }
className="wp-block-navigation-link__label"
value={ label }
onChange={ ( labelValue ) =>
setAttributes( { label: labelValue } )
}
placeholder={ itemLabelPlaceholder }
keepPlaceholderOnFocus
withoutInteractiveFormatting
allowedFormats={ [
'core/bold',
'core/italic',
'core/image',
'core/strikethrough',
] }
/>
{ cloneElement( editField, { ref } ) }
{ isLinkOpen && (
<Popover
position="bottom center"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
NavigableToolbar,
BlockNavigationDropdown,
ToolSelector,
__experimentalBlockNavigationContext as BlockNavigationContext,
} from '@wordpress/block-editor';
import {
TableOfContents,
Expand All @@ -18,6 +19,8 @@ import {
import { Button } from '@wordpress/components';
import { plus } from '@wordpress/icons';

const blockNavigationContext = { withBlockNavigationSlots: false };

function HeaderToolbar( { onToggleInserter, isInserterOpen } ) {
const {
hasFixedToolbar,
Expand Down Expand Up @@ -77,7 +80,9 @@ function HeaderToolbar( { onToggleInserter, isInserterOpen } ) {
<EditorHistoryUndo />
<EditorHistoryRedo />
<TableOfContents hasOutlineItemsDisabled={ isTextModeEnabled } />
<BlockNavigationDropdown isDisabled={ isTextModeEnabled } />
<BlockNavigationContext.Provider value={ blockNavigationContext }>
<BlockNavigationDropdown isDisabled={ isTextModeEnabled } />
</BlockNavigationContext.Provider>
{ displayBlockToolbar && (
<div className="edit-post-header-toolbar__block-toolbar">
<BlockToolbar hideDragHandle />
Expand Down

0 comments on commit 32543c0

Please sign in to comment.