From 8b4eadb4ae8400558452fd86703803e03c546236 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Tue, 14 Sep 2021 09:43:19 +0100 Subject: [PATCH 01/34] Scaffold out very basic interface --- .../src/components/layout/index.js | 15 ++++++ .../secondary-sidebar/inserter-sidebar.js | 46 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js diff --git a/packages/edit-navigation/src/components/layout/index.js b/packages/edit-navigation/src/components/layout/index.js index 6b03909cf2be3b..6d75ac523fc174 100644 --- a/packages/edit-navigation/src/components/layout/index.js +++ b/packages/edit-navigation/src/components/layout/index.js @@ -34,6 +34,7 @@ import Sidebar from '../sidebar'; import Header from '../header'; import Notices from '../notices'; import Editor from '../editor'; +import InserterSidebar from '../secondary-sidebar/inserter-sidebar'; import UnsavedChangesWarning from './unsaved-changes-warning'; import { store as editNavigationStore } from '../../store'; @@ -44,8 +45,11 @@ const interfaceLabels = { body: __( 'Navigation menu blocks' ), /* translators: accessibility text for the navigation screen settings landmark region. */ sidebar: __( 'Navigation settings' ), + secondarySidebar: __( 'Block library' ), }; +const isInserterOpened = true; + export default function Layout( { blockEditorSettings } ) { const contentAreaRef = useBlockSelectionClearer(); const [ isMenuNameControlFocused, setIsMenuNameControlFocused ] = useState( @@ -95,6 +99,16 @@ export default function Layout( { blockEditorSettings } ) { isMenuSelected ); + const secondarySidebar = () => { + // Todo: enable mode in Nav Editor store + // mode && mode === 'visual' && + if ( isInserterOpened ) { + return ; + } + + return null; + }; + return ( @@ -175,6 +189,7 @@ export default function Layout( { blockEditorSettings } ) { ) } + secondarySidebar={ secondarySidebar() } /> { isMenuSelected && ( +
+
+
+ +
+ + ); +} + +export default InserterSidebar; From 91c11d2a6a47e33fb132b50019712fafea8111f1 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Tue, 7 Sep 2021 14:27:20 +0100 Subject: [PATCH 02/34] Wire up store state and UI --- .../secondary-sidebar/inserter-sidebar.js | 25 +++++++++++++------ packages/edit-navigation/src/store/actions.js | 19 ++++++++++++++ packages/edit-navigation/src/store/reducer.js | 15 +++++++++++ .../edit-navigation/src/store/selectors.js | 11 ++++++++ 4 files changed, 63 insertions(+), 7 deletions(-) diff --git a/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js b/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js index 1992d5996575e1..4657c987a088cb 100644 --- a/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js +++ b/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js @@ -6,18 +6,31 @@ import { close } from '@wordpress/icons'; import { __experimentalLibrary as Library } from '@wordpress/block-editor'; import { useViewportMatch } from '@wordpress/compose'; import { useRef } from '@wordpress/element'; +import { useDispatch, useSelect } from '@wordpress/data'; + +/** + * Internal dependencies + */ +import { store as editNavigationStore } from '../../store'; function InserterSidebar() { const isMobileViewport = useViewportMatch( 'medium', '<' ); - // Todo: make these dynamic. - const insertionIndex = 0; + const { isInserterOpened } = useSelect( ( select ) => { + return { + isInserterOpened: select( editNavigationStore ).isInserterOpened(), + }; + } ); + + const { setIsInserterOpened } = useDispatch( editNavigationStore ); + const inserterDialogRef = useRef(); const inserterDialogProps = {}; - const rootClientId = '0'; - // Todo: implement in store. - function setIsInserterOpened() {} + // Don't display if not opened. + if ( ! isInserterOpened ) { + return null; + } return (
diff --git a/packages/edit-navigation/src/store/actions.js b/packages/edit-navigation/src/store/actions.js index 587e4cf62e0805..91b2cc7500197d 100644 --- a/packages/edit-navigation/src/store/actions.js +++ b/packages/edit-navigation/src/store/actions.js @@ -215,3 +215,22 @@ function* batchSave( menuId, menuItemsByClientId, navigationBlock ) { body, } ); } + +/** + * Returns an action object used to open/close the inserter. + * + * @param {boolean|Object} value Whether the inserter should be + * opened (true) or closed (false). + * To specify an insertion point, + * use an object. + * @param {string} value.rootClientId The root client ID to insert at. + * @param {number} value.insertionIndex The index to insert at. + * + * @return {Object} Action object. + */ +export function setIsInserterOpened( value ) { + return { + type: 'SET_IS_INSERTER_OPENED', + value, + }; +} diff --git a/packages/edit-navigation/src/store/reducer.js b/packages/edit-navigation/src/store/reducer.js index ba95ce158d33ce..ae778ab5746f6e 100644 --- a/packages/edit-navigation/src/store/reducer.js +++ b/packages/edit-navigation/src/store/reducer.js @@ -98,8 +98,23 @@ export function selectedMenuId( state = null, action ) { return state; } +/** + * Reducer tracking whether the inserter is open. + * + * @param {boolean|Object} state + * @param {Object} action + */ +function blockInserterPanel( state = false, action ) { + switch ( action.type ) { + case 'SET_IS_INSERTER_OPENED': + return action.value; + } + return state; +} + export default combineReducers( { mapping, processingQueue, selectedMenuId, + blockInserterPanel, } ); diff --git a/packages/edit-navigation/src/store/selectors.js b/packages/edit-navigation/src/store/selectors.js index 4005db4c9b00e2..b554117ed8ebcf 100644 --- a/packages/edit-navigation/src/store/selectors.js +++ b/packages/edit-navigation/src/store/selectors.js @@ -81,3 +81,14 @@ export const getMenuItemForClientId = createRegistrySelector( return select( coreStore ).getMenuItem( mapping[ clientId ] ); } ); + +/** + * Returns true if the inserter is opened. + * + * @param {Object} state Global application state. + * + * @return {boolean} Whether the inserter is opened. + */ +export function isInserterOpened( state = false ) { + return !! state.blockInserterPanel; +} From 04a1008c31606ab2fd3d066a1d553eed4feb7301 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Tue, 7 Sep 2021 14:36:31 +0100 Subject: [PATCH 03/34] Add inserter button to header toolbar --- .../src/components/header/index.js | 43 ++++++++++++++++++- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/packages/edit-navigation/src/components/header/index.js b/packages/edit-navigation/src/components/header/index.js index 228b53b520ff8e..bfbd146e3a2420 100644 --- a/packages/edit-navigation/src/components/header/index.js +++ b/packages/edit-navigation/src/components/header/index.js @@ -2,11 +2,14 @@ * WordPress dependencies */ import { NavigableToolbar } from '@wordpress/block-editor'; -import { DropdownMenu } from '@wordpress/components'; +import { DropdownMenu, Button, ToolbarItem } from '@wordpress/components'; import { useViewportMatch } from '@wordpress/compose'; import { PinnedItems } from '@wordpress/interface'; -import { __, sprintf } from '@wordpress/i18n'; +import { __, sprintf, _x } from '@wordpress/i18n'; import { decodeEntities } from '@wordpress/html-entities'; +import { useRef } from '@wordpress/element'; +import { useSelect, useDispatch } from '@wordpress/data'; +import { plus } from '@wordpress/icons'; /** * Internal dependencies @@ -16,6 +19,7 @@ import UndoButton from './undo-button'; import RedoButton from './redo-button'; import MenuSwitcher from '../menu-switcher'; import { useMenuEntityProp } from '../../hooks'; +import { store as editNavigationStore } from '../../store'; export default function Header( { isMenuSelected, @@ -25,8 +29,18 @@ export default function Header( { isPending, navigationPost, } ) { + const inserterButton = useRef(); const isMediumViewport = useViewportMatch( 'medium' ); const [ menuName ] = useMenuEntityProp( 'name', selectedMenuId ); + + const { isInserterOpened } = useSelect( ( select ) => { + return { + isInserterOpened: select( editNavigationStore ).isInserterOpened(), + }; + } ); + + const { setIsInserterOpened } = useDispatch( editNavigationStore ); + let actionHeaderText; if ( menuName ) { @@ -53,6 +67,31 @@ export default function Header( { className="edit-navigation-header__toolbar" aria-label={ __( 'Document tools' ) } > + { + event.preventDefault(); + } } + onClick={ () => { + if ( isInserterOpened ) { + // Focusing the inserter button closes the inserter popover + // @ts-ignore + inserterButton.current.focus(); + } else { + setIsInserterOpened( true ); + } + } } + icon={ plus } + label={ _x( + 'Add block', + 'Generic label for block inserter button' + ) } + /> + From 080da88d5b078be9165a01b7dca30e63e2ad78a0 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Tue, 7 Sep 2021 14:37:36 +0100 Subject: [PATCH 04/34] Use correct classname --- packages/edit-navigation/src/components/header/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-navigation/src/components/header/index.js b/packages/edit-navigation/src/components/header/index.js index bfbd146e3a2420..d78d9e2933a6c8 100644 --- a/packages/edit-navigation/src/components/header/index.js +++ b/packages/edit-navigation/src/components/header/index.js @@ -70,7 +70,7 @@ export default function Header( { { From ce85b36d853fb1b598426156e227fb4c7ebbe494 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Tue, 7 Sep 2021 15:37:12 +0100 Subject: [PATCH 05/34] Use optimal props on inserter toggle --- packages/edit-navigation/src/components/header/index.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/edit-navigation/src/components/header/index.js b/packages/edit-navigation/src/components/header/index.js index d78d9e2933a6c8..6e34f3549410cc 100644 --- a/packages/edit-navigation/src/components/header/index.js +++ b/packages/edit-navigation/src/components/header/index.js @@ -71,7 +71,7 @@ export default function Header( { ref={ inserterButton } as={ Button } className="edit-navigation-header-toolbar__inserter-toggle" - isPrimary + variant="primary" isPressed={ isInserterOpened } onMouseDown={ ( event ) => { event.preventDefault(); @@ -86,8 +86,10 @@ export default function Header( { } } } icon={ plus } + /* translators: button label text should, if possible, be under 16 + characters. */ label={ _x( - 'Add block', + 'Toggle block inserter', 'Generic label for block inserter button' ) } /> From a248cf257030cac892de0c7ce7c782b8cbe01c12 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Tue, 7 Sep 2021 15:37:35 +0100 Subject: [PATCH 06/34] Allow global inserter to insert blocks at root level of Nav block --- .../secondary-sidebar/inserter-sidebar.js | 5 +++++ packages/edit-navigation/src/hooks/index.js | 1 + .../use-navigation-editor-insertion-point.js | 21 +++++++++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 packages/edit-navigation/src/hooks/use-navigation-editor-insertion-point.js diff --git a/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js b/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js index 4657c987a088cb..ec3da9c01dd62b 100644 --- a/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js +++ b/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js @@ -12,10 +12,13 @@ import { useDispatch, useSelect } from '@wordpress/data'; * Internal dependencies */ import { store as editNavigationStore } from '../../store'; +import { useNavigationEditorInsertionPoint } from '../../hooks'; function InserterSidebar() { const isMobileViewport = useViewportMatch( 'medium', '<' ); + const { rootClientId } = useNavigationEditorInsertionPoint(); + const { isInserterOpened } = useSelect( ( select ) => { return { isInserterOpened: select( editNavigationStore ).isInserterOpened(), @@ -48,6 +51,8 @@ function InserterSidebar() { diff --git a/packages/edit-navigation/src/hooks/index.js b/packages/edit-navigation/src/hooks/index.js index 36ac7098254c52..7886aaa475aa7d 100644 --- a/packages/edit-navigation/src/hooks/index.js +++ b/packages/edit-navigation/src/hooks/index.js @@ -14,3 +14,4 @@ export { default as useNavigationBlockEditor } from './use-navigation-block-edit export { default as useMenuNotifications } from './use-menu-notifications'; export { default as useSelectedMenuId } from './use-selected-menu-id'; export { default as useMenuLocations } from './use-menu-locations'; +export { default as useNavigationEditorInsertionPoint } from './use-navigation-editor-insertion-point'; diff --git a/packages/edit-navigation/src/hooks/use-navigation-editor-insertion-point.js b/packages/edit-navigation/src/hooks/use-navigation-editor-insertion-point.js new file mode 100644 index 00000000000000..cdd3218c365048 --- /dev/null +++ b/packages/edit-navigation/src/hooks/use-navigation-editor-insertion-point.js @@ -0,0 +1,21 @@ +/** + * WordPress dependencies + */ +import { useSelect } from '@wordpress/data'; +import { store as blockEditorStore } from '@wordpress/block-editor'; + +/** + * Internal dependencies + */ + +const useNavigationEditorInsertionPoint = () => { + return useSelect( ( select ) => { + const { getBlockOrder } = select( blockEditorStore ); + + return { + rootClientId: getBlockOrder()[ 0 ], + }; + }, [] ); +}; + +export default useNavigationEditorInsertionPoint; From ff8c787ce00828a8a087462148aeac9bfb5befd2 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Tue, 7 Sep 2021 15:45:09 +0100 Subject: [PATCH 07/34] Avoid displaying inserter if there are no blocks to insert --- .../src/components/header/index.js | 18 +++++++++++++++--- .../secondary-sidebar/inserter-sidebar.js | 13 +++++++++---- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/packages/edit-navigation/src/components/header/index.js b/packages/edit-navigation/src/components/header/index.js index 6e34f3549410cc..590e9dae37de1b 100644 --- a/packages/edit-navigation/src/components/header/index.js +++ b/packages/edit-navigation/src/components/header/index.js @@ -1,7 +1,10 @@ /** * WordPress dependencies */ -import { NavigableToolbar } from '@wordpress/block-editor'; +import { + NavigableToolbar, + store as blockEditorStore, +} from '@wordpress/block-editor'; import { DropdownMenu, Button, ToolbarItem } from '@wordpress/components'; import { useViewportMatch } from '@wordpress/compose'; import { PinnedItems } from '@wordpress/interface'; @@ -18,7 +21,10 @@ import SaveButton from './save-button'; import UndoButton from './undo-button'; import RedoButton from './redo-button'; import MenuSwitcher from '../menu-switcher'; -import { useMenuEntityProp } from '../../hooks'; +import { + useMenuEntityProp, + useNavigationEditorInsertionPoint, +} from '../../hooks'; import { store as editNavigationStore } from '../../store'; export default function Header( { @@ -33,8 +39,13 @@ export default function Header( { const isMediumViewport = useViewportMatch( 'medium' ); const [ menuName ] = useMenuEntityProp( 'name', selectedMenuId ); - const { isInserterOpened } = useSelect( ( select ) => { + const { rootClientId } = useNavigationEditorInsertionPoint(); + + const { isInserterOpened, hasInserterItems } = useSelect( ( select ) => { return { + hasInserterItems: select( blockEditorStore ).hasInserterItems( + rootClientId + ), isInserterOpened: select( editNavigationStore ).isInserterOpened(), }; } ); @@ -92,6 +103,7 @@ export default function Header( { 'Toggle block inserter', 'Generic label for block inserter button' ) } + disabled={ ! hasInserterItems } /> diff --git a/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js b/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js index ec3da9c01dd62b..6cb72ae6c447fc 100644 --- a/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js +++ b/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js @@ -3,7 +3,10 @@ */ import { Button } from '@wordpress/components'; import { close } from '@wordpress/icons'; -import { __experimentalLibrary as Library } from '@wordpress/block-editor'; +import { + __experimentalLibrary as Library, + store as blockEditorStore, +} from '@wordpress/block-editor'; import { useViewportMatch } from '@wordpress/compose'; import { useRef } from '@wordpress/element'; import { useDispatch, useSelect } from '@wordpress/data'; @@ -19,8 +22,11 @@ function InserterSidebar() { const { rootClientId } = useNavigationEditorInsertionPoint(); - const { isInserterOpened } = useSelect( ( select ) => { + const { isInserterOpened, hasInserterItems } = useSelect( ( select ) => { return { + hasInserterItems: select( blockEditorStore ).hasInserterItems( + rootClientId + ), isInserterOpened: select( editNavigationStore ).isInserterOpened(), }; } ); @@ -30,8 +36,7 @@ function InserterSidebar() { const inserterDialogRef = useRef(); const inserterDialogProps = {}; - // Don't display if not opened. - if ( ! isInserterOpened ) { + if ( ! isInserterOpened || ! hasInserterItems ) { return null; } From cf3a33f887110eac652d5262a7ddf9bc943c2ba0 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Tue, 7 Sep 2021 16:03:13 +0100 Subject: [PATCH 08/34] Hide previews as they don't provide much value here --- .../src/components/secondary-sidebar/inserter-sidebar.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js b/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js index 6cb72ae6c447fc..ab2c0a28722185 100644 --- a/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js +++ b/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js @@ -18,6 +18,8 @@ import { store as editNavigationStore } from '../../store'; import { useNavigationEditorInsertionPoint } from '../../hooks'; function InserterSidebar() { + const SHOW_PREVIEWS = false; + const isMobileViewport = useViewportMatch( 'medium', '<' ); const { rootClientId } = useNavigationEditorInsertionPoint(); @@ -54,10 +56,10 @@ function InserterSidebar() {
From 3338882f11f50190433c884ddd497afca7b8fd78 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 8 Sep 2021 10:09:00 +0100 Subject: [PATCH 09/34] Refactor Inserter to dedicate component --- .../src/components/header/index.js | 62 ++---------------- .../src/components/header/inserter.js | 63 +++++++++++++++++++ .../use-navigation-editor-insertion-point.js | 4 +- 3 files changed, 72 insertions(+), 57 deletions(-) create mode 100644 packages/edit-navigation/src/components/header/inserter.js diff --git a/packages/edit-navigation/src/components/header/index.js b/packages/edit-navigation/src/components/header/index.js index 590e9dae37de1b..0b16aaa883ecd6 100644 --- a/packages/edit-navigation/src/components/header/index.js +++ b/packages/edit-navigation/src/components/header/index.js @@ -1,18 +1,12 @@ /** * WordPress dependencies */ -import { - NavigableToolbar, - store as blockEditorStore, -} from '@wordpress/block-editor'; -import { DropdownMenu, Button, ToolbarItem } from '@wordpress/components'; +import { NavigableToolbar } from '@wordpress/block-editor'; +import { DropdownMenu } from '@wordpress/components'; import { useViewportMatch } from '@wordpress/compose'; import { PinnedItems } from '@wordpress/interface'; -import { __, sprintf, _x } from '@wordpress/i18n'; +import { __, sprintf } from '@wordpress/i18n'; import { decodeEntities } from '@wordpress/html-entities'; -import { useRef } from '@wordpress/element'; -import { useSelect, useDispatch } from '@wordpress/data'; -import { plus } from '@wordpress/icons'; /** * Internal dependencies @@ -20,12 +14,9 @@ import { plus } from '@wordpress/icons'; import SaveButton from './save-button'; import UndoButton from './undo-button'; import RedoButton from './redo-button'; +import Inserter from './inserter'; import MenuSwitcher from '../menu-switcher'; -import { - useMenuEntityProp, - useNavigationEditorInsertionPoint, -} from '../../hooks'; -import { store as editNavigationStore } from '../../store'; +import { useMenuEntityProp } from '../../hooks'; export default function Header( { isMenuSelected, @@ -35,23 +26,9 @@ export default function Header( { isPending, navigationPost, } ) { - const inserterButton = useRef(); const isMediumViewport = useViewportMatch( 'medium' ); const [ menuName ] = useMenuEntityProp( 'name', selectedMenuId ); - const { rootClientId } = useNavigationEditorInsertionPoint(); - - const { isInserterOpened, hasInserterItems } = useSelect( ( select ) => { - return { - hasInserterItems: select( blockEditorStore ).hasInserterItems( - rootClientId - ), - isInserterOpened: select( editNavigationStore ).isInserterOpened(), - }; - } ); - - const { setIsInserterOpened } = useDispatch( editNavigationStore ); - let actionHeaderText; if ( menuName ) { @@ -78,34 +55,7 @@ export default function Header( { className="edit-navigation-header__toolbar" aria-label={ __( 'Document tools' ) } > - { - event.preventDefault(); - } } - onClick={ () => { - if ( isInserterOpened ) { - // Focusing the inserter button closes the inserter popover - // @ts-ignore - inserterButton.current.focus(); - } else { - setIsInserterOpened( true ); - } - } } - icon={ plus } - /* translators: button label text should, if possible, be under 16 - characters. */ - label={ _x( - 'Toggle block inserter', - 'Generic label for block inserter button' - ) } - disabled={ ! hasInserterItems } - /> - + diff --git a/packages/edit-navigation/src/components/header/inserter.js b/packages/edit-navigation/src/components/header/inserter.js new file mode 100644 index 00000000000000..58553177972935 --- /dev/null +++ b/packages/edit-navigation/src/components/header/inserter.js @@ -0,0 +1,63 @@ +/** + * WordPress dependencies + */ +import { store as blockEditorStore } from '@wordpress/block-editor'; +import { Button, ToolbarItem } from '@wordpress/components'; +import { _x } from '@wordpress/i18n'; +import { useRef } from '@wordpress/element'; +import { useSelect, useDispatch } from '@wordpress/data'; +import { plus } from '@wordpress/icons'; + +/** + * Internal dependencies + */ +import { useNavigationEditorInsertionPoint } from '../../hooks'; +import { store as editNavigationStore } from '../../store'; + +function Inserter() { + const inserterButton = useRef(); + const { rootClientId } = useNavigationEditorInsertionPoint(); + + const { isInserterOpened, hasInserterItems } = useSelect( ( select ) => { + return { + hasInserterItems: select( blockEditorStore ).hasInserterItems( + rootClientId + ), + isInserterOpened: select( editNavigationStore ).isInserterOpened(), + }; + } ); + + const { setIsInserterOpened } = useDispatch( editNavigationStore ); + + return ( + { + event.preventDefault(); + } } + onClick={ () => { + if ( isInserterOpened ) { + // Focusing the inserter button closes the inserter popover + // @ts-ignore + inserterButton.current.focus(); + } else { + setIsInserterOpened( true ); + } + } } + icon={ plus } + /* translators: button label text should, if possible, be under 16 + characters. */ + label={ _x( + 'Toggle block inserter', + 'Generic label for block inserter button' + ) } + disabled={ ! hasInserterItems } + /> + ); +} + +export default Inserter; diff --git a/packages/edit-navigation/src/hooks/use-navigation-editor-insertion-point.js b/packages/edit-navigation/src/hooks/use-navigation-editor-insertion-point.js index cdd3218c365048..f4d203f36d3c61 100644 --- a/packages/edit-navigation/src/hooks/use-navigation-editor-insertion-point.js +++ b/packages/edit-navigation/src/hooks/use-navigation-editor-insertion-point.js @@ -12,8 +12,10 @@ const useNavigationEditorInsertionPoint = () => { return useSelect( ( select ) => { const { getBlockOrder } = select( blockEditorStore ); + const lockedNavigationBlock = getBlockOrder()[ 0 ]; + return { - rootClientId: getBlockOrder()[ 0 ], + rootClientId: lockedNavigationBlock, }; }, [] ); }; From 14f0e31ea68c9b0bdb381636fb7566f1fcc8c45c Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 8 Sep 2021 10:12:03 +0100 Subject: [PATCH 10/34] Remove hardcoded conditional --- .../edit-navigation/src/components/layout/index.js | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/packages/edit-navigation/src/components/layout/index.js b/packages/edit-navigation/src/components/layout/index.js index 6d75ac523fc174..831ff7eda1993f 100644 --- a/packages/edit-navigation/src/components/layout/index.js +++ b/packages/edit-navigation/src/components/layout/index.js @@ -48,8 +48,6 @@ const interfaceLabels = { secondarySidebar: __( 'Block library' ), }; -const isInserterOpened = true; - export default function Layout( { blockEditorSettings } ) { const contentAreaRef = useBlockSelectionClearer(); const [ isMenuNameControlFocused, setIsMenuNameControlFocused ] = useState( @@ -99,15 +97,7 @@ export default function Layout( { blockEditorSettings } ) { isMenuSelected ); - const secondarySidebar = () => { - // Todo: enable mode in Nav Editor store - // mode && mode === 'visual' && - if ( isInserterOpened ) { - return ; - } - - return null; - }; + const secondarySidebar = () => ; return ( From a30ac837d805feedf19c6a90aafda3ff2186f800 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 8 Sep 2021 10:20:32 +0100 Subject: [PATCH 11/34] Remove unwanted ref usage --- .../src/components/secondary-sidebar/inserter-sidebar.js | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js b/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js index ab2c0a28722185..7d55187efe625c 100644 --- a/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js +++ b/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js @@ -8,7 +8,6 @@ import { store as blockEditorStore, } from '@wordpress/block-editor'; import { useViewportMatch } from '@wordpress/compose'; -import { useRef } from '@wordpress/element'; import { useDispatch, useSelect } from '@wordpress/data'; /** @@ -35,7 +34,6 @@ function InserterSidebar() { const { setIsInserterOpened } = useDispatch( editNavigationStore ); - const inserterDialogRef = useRef(); const inserterDialogProps = {}; if ( ! isInserterOpened || ! hasInserterItems ) { @@ -44,7 +42,6 @@ function InserterSidebar() { return (
From c8679369ae469fc28edb648d130b8fe315d1416a Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 8 Sep 2021 10:47:20 +0100 Subject: [PATCH 12/34] Add toggle button styles and remove close button on larger screens --- .../src/components/header/inserter.js | 10 +----- .../src/components/header/style.scss | 31 +++++++++++++++++++ .../secondary-sidebar/inserter-sidebar.js | 6 ++-- 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/packages/edit-navigation/src/components/header/inserter.js b/packages/edit-navigation/src/components/header/inserter.js index 58553177972935..237348fe8f6192 100644 --- a/packages/edit-navigation/src/components/header/inserter.js +++ b/packages/edit-navigation/src/components/header/inserter.js @@ -39,15 +39,7 @@ function Inserter() { onMouseDown={ ( event ) => { event.preventDefault(); } } - onClick={ () => { - if ( isInserterOpened ) { - // Focusing the inserter button closes the inserter popover - // @ts-ignore - inserterButton.current.focus(); - } else { - setIsInserterOpened( true ); - } - } } + onClick={ () => setIsInserterOpened( ! isInserterOpened ) } icon={ plus } /* translators: button label text should, if possible, be under 16 characters. */ diff --git a/packages/edit-navigation/src/components/header/style.scss b/packages/edit-navigation/src/components/header/style.scss index bc940b93a14bc2..ffdaca7ce316c9 100644 --- a/packages/edit-navigation/src/components/header/style.scss +++ b/packages/edit-navigation/src/components/header/style.scss @@ -75,3 +75,34 @@ display: none; } } + + +// INSERTER TOGGLE +.edit-navigation-header-toolbar__inserter-toggle { + + svg { + transition: transform cubic-bezier(0.165, 0.84, 0.44, 1) 0.2s; + @include reduce-motion("transition"); + } + + // Make the button appear like a "X" close button. + &.is-pressed { + svg { + transform: rotate(45deg); + } + } +} + +// INSERTER PANEL +.edit-navigation-layout__inserter-panel-header { + padding-top: $grid-unit-10; + padding-right: $grid-unit-10; + display: flex; + justify-content: flex-end; + + // Hide close button within panel on larger screens as this + // action is provided by the inserter toggle or ESC key. + @include break-medium() { + display: none; + } +} diff --git a/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js b/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js index 7d55187efe625c..2a6bb689e363a4 100644 --- a/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js +++ b/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js @@ -43,15 +43,15 @@ function InserterSidebar() { return (
-
+
-
+
Date: Wed, 8 Sep 2021 11:24:30 +0100 Subject: [PATCH 13/34] Allow tools to show on mobile viewports --- .../src/components/header/index.js | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/packages/edit-navigation/src/components/header/index.js b/packages/edit-navigation/src/components/header/index.js index 0b16aaa883ecd6..3b7594103e5fe1 100644 --- a/packages/edit-navigation/src/components/header/index.js +++ b/packages/edit-navigation/src/components/header/index.js @@ -46,21 +46,22 @@ export default function Header( { return (
- { isMediumViewport && ( -
+
+ { isMediumViewport && (

{ __( 'Navigation' ) }

- - - - - -
- ) } + ) } + + + + + +
+

{ isMenuSelected && decodeEntities( actionHeaderText ) }

From 88c5de6bc80828db71ca3e3ebd06f343e2446211 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Tue, 14 Sep 2021 09:47:38 +0100 Subject: [PATCH 14/34] Conditionalise render of sidebar Ensures main content is visible on mobile devices when sidebar is disabled. If we return a component to the secondarySidebar then the interface component will render the wrapping div which will obscure the wrapping content. --- .../src/components/layout/index.js | 15 ++++++++++++--- .../secondary-sidebar/inserter-sidebar.js | 7 ++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/packages/edit-navigation/src/components/layout/index.js b/packages/edit-navigation/src/components/layout/index.js index 831ff7eda1993f..e24030e150b9aa 100644 --- a/packages/edit-navigation/src/components/layout/index.js +++ b/packages/edit-navigation/src/components/layout/index.js @@ -72,11 +72,12 @@ export default function Layout( { blockEditorSettings } ) { navigationPost ); - const { hasSidebarEnabled } = useSelect( + const { hasSidebarEnabled, isInserterOpened } = useSelect( ( select ) => ( { hasSidebarEnabled: !! select( interfaceStore ).getActiveComplementaryArea( 'core/edit-navigation' ), + isInserterOpened: select( editNavigationStore ).isInserterOpened(), } ), [] ); @@ -97,7 +98,15 @@ export default function Layout( { blockEditorSettings } ) { isMenuSelected ); - const secondarySidebar = () => ; + // Conditionally render at Layout level to ensure main content + // is visible on mobile. + const renderSecondarySidebar = () => { + if ( isInserterOpened ) { + return ; + } + + return null; + }; return ( @@ -179,7 +188,7 @@ export default function Layout( { blockEditorSettings } ) { ) } - secondarySidebar={ secondarySidebar() } + secondarySidebar={ renderSecondarySidebar() } /> { isMenuSelected && ( { + const { hasInserterItems } = useSelect( ( select ) => { return { hasInserterItems: select( blockEditorStore ).hasInserterItems( rootClientId ), - isInserterOpened: select( editNavigationStore ).isInserterOpened(), }; } ); @@ -36,7 +35,9 @@ function InserterSidebar() { const inserterDialogProps = {}; - if ( ! isInserterOpened || ! hasInserterItems ) { + // Only concerned with whether there are items to display. If not then + // we shouldn't render. + if ( ! hasInserterItems ) { return null; } From 21b9b0e8256b4195d37ed630a8ca3e840e955fcc Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 8 Sep 2021 11:46:56 +0100 Subject: [PATCH 15/34] Only hide undo/redo on smaller viewports --- .../edit-navigation/src/components/header/index.js | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/edit-navigation/src/components/header/index.js b/packages/edit-navigation/src/components/header/index.js index 3b7594103e5fe1..bc37aec5da7233 100644 --- a/packages/edit-navigation/src/components/header/index.js +++ b/packages/edit-navigation/src/components/header/index.js @@ -27,6 +27,7 @@ export default function Header( { navigationPost, } ) { const isMediumViewport = useViewportMatch( 'medium' ); + const [ menuName ] = useMenuEntityProp( 'name', selectedMenuId ); let actionHeaderText; @@ -52,19 +53,25 @@ export default function Header( { { __( 'Navigation' ) } ) } + - - + { isMediumViewport && ( + <> + + + + ) }

{ isMenuSelected && decodeEntities( actionHeaderText ) }

+ { isMenuSelected && (
Date: Wed, 8 Sep 2021 12:12:47 +0100 Subject: [PATCH 16/34] Simplify Navigation Block hook --- .../src/components/header/inserter.js | 6 +++--- .../secondary-sidebar/inserter-sidebar.js | 18 ++++++------------ packages/edit-navigation/src/hooks/index.js | 2 +- ....js => use-navigation-editor-root-block.js} | 6 +++--- 4 files changed, 13 insertions(+), 19 deletions(-) rename packages/edit-navigation/src/hooks/{use-navigation-editor-insertion-point.js => use-navigation-editor-root-block.js} (72%) diff --git a/packages/edit-navigation/src/components/header/inserter.js b/packages/edit-navigation/src/components/header/inserter.js index 237348fe8f6192..2501acd742eadf 100644 --- a/packages/edit-navigation/src/components/header/inserter.js +++ b/packages/edit-navigation/src/components/header/inserter.js @@ -11,17 +11,17 @@ import { plus } from '@wordpress/icons'; /** * Internal dependencies */ -import { useNavigationEditorInsertionPoint } from '../../hooks'; +import { useNavigationEditorRootBlock } from '../../hooks'; import { store as editNavigationStore } from '../../store'; function Inserter() { const inserterButton = useRef(); - const { rootClientId } = useNavigationEditorInsertionPoint(); + const { clientId: navBlockClientId } = useNavigationEditorRootBlock(); const { isInserterOpened, hasInserterItems } = useSelect( ( select ) => { return { hasInserterItems: select( blockEditorStore ).hasInserterItems( - rootClientId + navBlockClientId ), isInserterOpened: select( editNavigationStore ).isInserterOpened(), }; diff --git a/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js b/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js index 2901bd7dbccc7f..80bf515ec7a083 100644 --- a/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js +++ b/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js @@ -14,27 +14,25 @@ import { useDispatch, useSelect } from '@wordpress/data'; * Internal dependencies */ import { store as editNavigationStore } from '../../store'; -import { useNavigationEditorInsertionPoint } from '../../hooks'; +import { useNavigationEditorRootBlock } from '../../hooks'; function InserterSidebar() { const SHOW_PREVIEWS = false; const isMobileViewport = useViewportMatch( 'medium', '<' ); - const { rootClientId } = useNavigationEditorInsertionPoint(); + const { clientId: navBlockClientId } = useNavigationEditorRootBlock(); const { hasInserterItems } = useSelect( ( select ) => { return { hasInserterItems: select( blockEditorStore ).hasInserterItems( - rootClientId + navBlockClientId ), }; - } ); + }, [] ); const { setIsInserterOpened } = useDispatch( editNavigationStore ); - const inserterDialogProps = {}; - // Only concerned with whether there are items to display. If not then // we shouldn't render. if ( ! hasInserterItems ) { @@ -42,10 +40,7 @@ function InserterSidebar() { } return ( -
+
diff --git a/packages/edit-navigation/src/hooks/index.js b/packages/edit-navigation/src/hooks/index.js index 7886aaa475aa7d..2e5b4c072dd176 100644 --- a/packages/edit-navigation/src/hooks/index.js +++ b/packages/edit-navigation/src/hooks/index.js @@ -14,4 +14,4 @@ export { default as useNavigationBlockEditor } from './use-navigation-block-edit export { default as useMenuNotifications } from './use-menu-notifications'; export { default as useSelectedMenuId } from './use-selected-menu-id'; export { default as useMenuLocations } from './use-menu-locations'; -export { default as useNavigationEditorInsertionPoint } from './use-navigation-editor-insertion-point'; +export { default as useNavigationEditorRootBlock } from './use-navigation-editor-root-block'; diff --git a/packages/edit-navigation/src/hooks/use-navigation-editor-insertion-point.js b/packages/edit-navigation/src/hooks/use-navigation-editor-root-block.js similarity index 72% rename from packages/edit-navigation/src/hooks/use-navigation-editor-insertion-point.js rename to packages/edit-navigation/src/hooks/use-navigation-editor-root-block.js index f4d203f36d3c61..eb10355df2ce01 100644 --- a/packages/edit-navigation/src/hooks/use-navigation-editor-insertion-point.js +++ b/packages/edit-navigation/src/hooks/use-navigation-editor-root-block.js @@ -8,16 +8,16 @@ import { store as blockEditorStore } from '@wordpress/block-editor'; * Internal dependencies */ -const useNavigationEditorInsertionPoint = () => { +const useNavigationEditorRootBlock = () => { return useSelect( ( select ) => { const { getBlockOrder } = select( blockEditorStore ); const lockedNavigationBlock = getBlockOrder()[ 0 ]; return { - rootClientId: lockedNavigationBlock, + clientId: lockedNavigationBlock, }; }, [] ); }; -export default useNavigationEditorInsertionPoint; +export default useNavigationEditorRootBlock; From 70354c802e608ffa630c00529e4c7dd209693bea Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Wed, 8 Sep 2021 12:19:55 +0100 Subject: [PATCH 17/34] Ensure global inserter always targets root nav block --- .../secondary-sidebar/inserter-sidebar.js | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js b/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js index 80bf515ec7a083..324a51d1907219 100644 --- a/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js +++ b/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js @@ -23,13 +23,19 @@ function InserterSidebar() { const { clientId: navBlockClientId } = useNavigationEditorRootBlock(); - const { hasInserterItems } = useSelect( ( select ) => { - return { - hasInserterItems: select( blockEditorStore ).hasInserterItems( - navBlockClientId - ), - }; - }, [] ); + const { hasInserterItems, selectedBlockClientId } = useSelect( + ( select ) => { + return { + hasInserterItems: select( blockEditorStore ).hasInserterItems( + navBlockClientId + ), + selectedBlockClientId: select( + blockEditorStore + ).getSelectedBlock()?.clientId, + }; + }, + [] + ); const { setIsInserterOpened } = useDispatch( editNavigationStore ); @@ -51,6 +57,11 @@ function InserterSidebar() {
From 8d1d7c80d75ad5d1c966ff6afacf3c41cbdee8a0 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Thu, 9 Sep 2021 12:54:39 +0100 Subject: [PATCH 18/34] Ensure items always inserted at end if root nav block is selected --- .../secondary-sidebar/inserter-sidebar.js | 16 +++++++++++----- .../hooks/use-navigation-editor-root-block.js | 4 +++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js b/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js index 324a51d1907219..a375f483e81cab 100644 --- a/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js +++ b/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js @@ -21,7 +21,10 @@ function InserterSidebar() { const isMobileViewport = useViewportMatch( 'medium', '<' ); - const { clientId: navBlockClientId } = useNavigationEditorRootBlock(); + const { + navBlockClientId, + lastNavBlockItemIndex, + } = useNavigationEditorRootBlock(); const { hasInserterItems, selectedBlockClientId } = useSelect( ( select ) => { @@ -45,6 +48,8 @@ function InserterSidebar() { return null; } + const isNavBlockSelected = navBlockClientId === selectedBlockClientId; + return (
@@ -57,10 +62,11 @@ function InserterSidebar() { diff --git a/packages/edit-navigation/src/hooks/use-navigation-editor-root-block.js b/packages/edit-navigation/src/hooks/use-navigation-editor-root-block.js index eb10355df2ce01..61ccf0751fbcce 100644 --- a/packages/edit-navigation/src/hooks/use-navigation-editor-root-block.js +++ b/packages/edit-navigation/src/hooks/use-navigation-editor-root-block.js @@ -15,7 +15,9 @@ const useNavigationEditorRootBlock = () => { const lockedNavigationBlock = getBlockOrder()[ 0 ]; return { - clientId: lockedNavigationBlock, + navBlockClientId: lockedNavigationBlock, + lastNavBlockItemIndex: getBlockOrder( lockedNavigationBlock ) + .length, }; }, [] ); }; From 497d8304b953bdd706b5de87a7cf6cd3cfae5f18 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Thu, 9 Sep 2021 13:15:44 +0100 Subject: [PATCH 19/34] Update to use correct exported variable name --- packages/edit-navigation/src/components/header/inserter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/edit-navigation/src/components/header/inserter.js b/packages/edit-navigation/src/components/header/inserter.js index 2501acd742eadf..160d8fbb05e273 100644 --- a/packages/edit-navigation/src/components/header/inserter.js +++ b/packages/edit-navigation/src/components/header/inserter.js @@ -16,7 +16,7 @@ import { store as editNavigationStore } from '../../store'; function Inserter() { const inserterButton = useRef(); - const { clientId: navBlockClientId } = useNavigationEditorRootBlock(); + const { navBlockClientId } = useNavigationEditorRootBlock(); const { isInserterOpened, hasInserterItems } = useSelect( ( select ) => { return { From d28bdafc427ec6e049b360343ad33b8b29f81a69 Mon Sep 17 00:00:00 2001 From: Dave Smith Date: Thu, 9 Sep 2021 13:16:29 +0100 Subject: [PATCH 20/34] Handle focus and tab trapping via hook --- .../secondary-sidebar/inserter-sidebar.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js b/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js index a375f483e81cab..ba31b7e8bf6384 100644 --- a/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js +++ b/packages/edit-navigation/src/components/secondary-sidebar/inserter-sidebar.js @@ -7,7 +7,10 @@ import { __experimentalLibrary as Library, store as blockEditorStore, } from '@wordpress/block-editor'; -import { useViewportMatch } from '@wordpress/compose'; +import { + useViewportMatch, + __experimentalUseDialog as useDialog, +} from '@wordpress/compose'; import { useDispatch, useSelect } from '@wordpress/data'; /** @@ -42,6 +45,10 @@ function InserterSidebar() { const { setIsInserterOpened } = useDispatch( editNavigationStore ); + const [ inserterDialogRef, inserterDialogProps ] = useDialog( { + onClose: () => setIsInserterOpened( false ), + } ); + // Only concerned with whether there are items to display. If not then // we shouldn't render. if ( ! hasInserterItems ) { @@ -51,7 +58,11 @@ function InserterSidebar() { const isNavBlockSelected = navBlockClientId === selectedBlockClientId; return ( -
+